Skip to content

Versioning

Shadowfen edited this page Jul 29, 2026 · 5 revisions

As your addon evolves, the structure of your saved variables may change. New settings may be added, existing settings may be renamed, data may be reorganized, or old values may need to be removed.

LibSavedVars uses version numbers to track changes to saved data and determine when a migration is required.

Versioning allows your addon to update existing user data automatically without requiring users to delete their SavedVariables files.


Why Use Versioning?

Saved variables persist across addon updates. This means users may have data created by an older version of your addon.

For example, version 1 of an addon may store:

{
    enabled = true
}

Later, version 2 reorganizes the data:

{
    general = {
        enabled = true
    }
}

Without version tracking, the addon cannot determine whether the existing data needs to be updated.

Versioning provides a way to identify the format of stored data and apply the required changes.


Setting the Version

Every saved variables creation function includes a version parameter.

Example:

local settings = LibSavedVars:NewAccountWide(
    "MyAddonSavedVariables",
    2,
    nil,
    defaults
)

The version number represents the current format of your saved data.

When LibSavedVars loads the saved variables, it compares:

  • The version stored with the user's data.
  • The version specified by the addon.

How Version Checking Works

When an addon loads:

  1. LibSavedVars reads the saved data version.
  2. The current addon version is compared against the stored version.
  3. If the versions match, no update is required.
  4. If the stored version is older, migrations are executed.
  5. After successful migration, the saved data version is updated.

Example:

Stored Version Addon Version Result
1 1 No migration
1 2 Run version 2 migration
2 5 Run migrations 3, 4, and 5
5 5 No migration

When to Increase the Version

Increase the version only when existing saved data must change.

Examples that require a version increase:

  • Renaming a setting.
  • Moving a setting to a new location.
  • Changing the data format.
  • Combining multiple settings.
  • Splitting one setting into multiple settings.
  • Removing obsolete data.
  • Moving data between account-wide and character storage.

Example:

Before:

settings.opacity

After:

settings.display.opacity

Because existing data must be moved, the saved variable version should increase.


Changes That Do Not Require a Version Increase

Not every addon update requires a new version.

Adding a new default value usually does not require a migration.

Version 1:

local defaults = {
    enabled = true,
}

Version 2:

local defaults = {
    enabled = true,
    showTooltips = true,
}

Existing users automatically receive:

settings.showTooltips == true

because the default value is supplied when no saved value exists.

No migration is necessary.


Versioning and Defaults

Defaults and versioning solve different problems.

Feature Purpose
Defaults Provides values for settings that do not exist.
Versioning Detects when existing saved data must be changed.

A useful rule:

  • New setting? Add it to the defaults table.
  • Changed existing data? Increase the version and migrate.

Migration Versions

Each migration is associated with the version it creates.

Example:

settings:Migrate(2, function(savedVars)

    -- Convert version 1 data to version 2

end)

settings:Migrate(3, function(savedVars)

    -- Convert version 2 data to version 3

end)

A user upgrading directly from version 1 to version 3 runs:

  1. Version 2 migration.
  2. Version 3 migration.

Each migration should only handle one version change.


Migration Order

Migrations execute in ascending version order.

Example:

settings:Migrate(2, migrateToVersion2)
settings:Migrate(3, migrateToVersion3)
settings:Migrate(4, migrateToVersion4)

Upgrade path:

Version 1
    |
    v
Migration 2
    |
    v
Migration 3
    |
    v
Migration 4
    |
    v
Version 4

This allows users to upgrade from any previous release without skipping required changes.


Versioning Best Practices

Keep Migrations Permanent

Once an addon has released a migration, do not remove or rewrite it.

A user may upgrade from an old version directly to the newest version.

Example:

Version 1
    |
    v
Version 2 migration
    |
    v
Version 3 migration
    |
    v
Current version

Removing the version 2 migration could prevent old users from upgrading correctly.


Make Migrations Small

Each migration should perform one logical update.

Good:

settings:Migrate(2, function(savedVars)

    savedVars.newName = savedVars.oldName
    savedVars.oldName = nil

end)

Avoid combining unrelated changes:

settings:Migrate(2, function(savedVars)

    -- rename settings
    -- restructure tables
    -- convert formats
    -- remove old data

end)

Test Older Data

Do not test only new installations.

Create saved variable data from older addon versions and verify that upgrading produces the expected result.

Test cases should include:

  • Fresh installation.
  • One-version upgrade.
  • Multiple-version upgrade.
  • Missing optional settings.
  • Existing customized values.

Versioning Example

Complete example:

local settings = LibSavedVars:NewAccountWide(
    "MyAddonSavedVariables",
    3,
    nil,
    defaults
)

settings:Migrate(2, function(savedVars)

    savedVars.general = savedVars.general or {}
    savedVars.general.enabled = savedVars.enabled
    savedVars.enabled = nil

end)

settings:Migrate(3, function(savedVars)

    savedVars.general.scale =
        savedVars.scale or 1.0

    savedVars.scale = nil

end)

A user upgrading from version 1 receives both updates automatically.


Summary

Versioning allows LibSavedVars addons to safely evolve their saved data structure over time.

Use version numbers to answer:

"Does this user's saved data need to be updated?"

Use migrations to answer:

"How should the saved data be updated?"

Together, versioning and migrations allow addons to add features, reorganize settings, and improve their design while preserving user preferences.

See Also

Clone this wiki locally