# Updating ESX Legacy (/docs/getting-started/updating)

Updating ESX Legacy is mostly a file swap: replace the core resources with the new release, start the server and let ESX migrate the database. What makes an update *safe* is everything around that swap: a backup you can restore, a list of your own changes, and a test run before players join. This page describes that process.

The current release is **1.16.4** (October 2026). Releases and changelogs are published at [github.com/esx-framework/esx_core/releases](https://github.com/esx-framework/esx_core/releases).

## Before you update [#before-you-update]

### Read the release notes [#read-the-release-notes]

Open the releases page and read every release between your version and the new one. Look for:

- removed or renamed functions and config keys (old scripts may depend on them)
- new dependencies (for example `esx_lib`, which `es_extended` now requires)
- manual SQL steps or changed convars

<Callout type="info" title="Version numbers in fxmanifest">
The `version` field in `fxmanifest.lua` is not always bumped with every release. In the 1.16.4 source, the core manifests still say `1.16.3`. Rely on the release tag and your download date, not only on the manifest.
</Callout>

### Back up everything [#back-up-everything]

1. **Database.** Export the full database, for example with HeidiSQL (**Tools > Export database as SQL**) or from the command line:

   ```bash
   mysqldump -u esx -p --single-transaction --routines es_extended > esx_backup_2026-10-20.sql
   ```

2. **Resources.** Copy the whole `resources` folder and `server.cfg`. A zip with the date in the name is enough.
3. **Check the backup.** Open the SQL file and confirm it contains `CREATE TABLE` and `INSERT` statements for `users`. A backup you never tested is a hope, not a backup.

### List your own changes [#list-your-own-changes]

If you edited files inside `es_extended` or other core resources, those edits will be overwritten. Find them before you update:

- If your resources are in git, `git diff` shows them.
- Otherwise compare your folder with the release you originally installed, using a diff tool such as WinMerge or Meld.

Move customizations out of core files where possible: settings belong in config files, new features in your own resources. The fewer edits you carry in the core, the easier every update gets.

## Update process [#update-process]

<Steps>
<Step>
### Stop the server [#stop-the-server]

Stop it in txAdmin or the console. Do not swap files while it runs.
</Step>

<Step>
### Replace the core resources [#replace-the-core-resources]

Download the release of `esx_core` and replace each resource in `resources/[core]` with the new version. Replace whole folders instead of copying files on top, so removed files do not stay behind.

Keep your edited config files aside and merge your values into the **new** config files afterwards. New releases often add config keys; an old config file can be missing them.

If you use the official addons, update `[esx_addons]` from [ESX-Legacy-Addons](https://github.com/esx-framework/ESX-Legacy-Addons) the same way. Also update `oxmysql` to its latest release.
</Step>

<Step>
### Update the server build [#update-the-server-build]

Use a recent FiveM server build. ESX refuses player connections on builds older than 10188, and new ESX releases are tested against current builds.
</Step>

<Step>
### Start the server and let migrations run [#start-the-server-and-let-migrations-run]

On startup `es_extended` runs its database migrations. Each ESX version that changed the schema (for example `v1.13.3`, `v1.13.5`, `v1.14.1`, `v1.16.0`) has a migration that runs once. You see:

```txt
[INFO] Running migrations for ESX version v1.16.0
[SUCCESS] Successfully completed migrations for ESX version v1.16.0
[INFO] Ran migrations for 1 ESX version(s). Server restart required!
```

When the restart message appears, ESX keeps repeating it until you restart. Restart the server once; the migrations are recorded and do not run again.

If a migration fails, the console prints `Failed migration ['<version>.<name>']` with the database error. Fix the cause (often duplicate data or a missing permission for your database user) and start again.
</Step>

<Step>
### Test before players join [#test-before-players-join]

Join with a test account and check the basics: character selection, money and inventory, a job action, a shop purchase, saving after reconnect. Watch the server console and F8 console for errors.
</Step>
</Steps>

## How ESX migrations work [#how-esx-migrations-work]

Migrations live in `es_extended/server/migration/<version>/`. When one completes, ESX stores a flag in the resource KVP store (`esx_migration:<version>`), so it is skipped on later starts. This means:

- You do not need to import `legacy.sql` again when updating. Never do that on a live database.
- If you restore a database backup from **before** a migration, the flags still say "done" and the migration will not rerun. Run `resetmigrations` in the **server console** (it refuses to run from in game), then restart. All migrations run again on the next start.

Some addons (`esx_billing`, `esx_license`, `esx_addonaccount`, `esx_banking`) also apply their own schema migrations automatically when they start.

## Optional: security hardening SQL (October 2026) [#optional-security-hardening-sql-october-2026]

The ESX-Legacy-Addons repository contains [`sql/security_hardening_2026_10_02.sql`](https://github.com/esx-framework/ESX-Legacy-Addons/blob/main/sql/security_hardening_2026_10_02.sql). It is a manual alternative to the automatic addon migrations mentioned above. It:

- adds a `billing_payments` table that makes bill payments idempotent
- adds a unique key on `user_licenses (owner, type)`
- adds an `owner_key` column and a unique key to `addon_account_data`
- adds indexes on `billing.identifier` and `banking.time`

Before it changes anything, it checks for duplicate licenses, duplicate or invalid addon accounts and economy tables that are not InnoDB. If it finds any, it stops with a message such as `Duplicate addon accounts: reconcile balances before migration` and changes nothing. It never merges or deletes financial rows for you.

Notes before running it:

- It requires **MySQL 8 or MariaDB 10.6+**.
- DDL statements commit immediately, so it is not a rollback-safe transaction. Take a backup first and run it in a maintenance window.
- It is safe to run more than once.
- The older `security_indexes.sql` in the same repository is superseded by this file.

## Updating old ESX (1.1, 1.2, v1 final) [#updating-old-esx-11-12-v1-final]

There is no in-place upgrade from the original ESX releases to ESX Legacy. The database layout, the inventory format and the API changed too much. The practical path is a fresh ESX Legacy install, then migrating your data and converting scripts one by one. See [Convert old ESX scripts](/docs/guides/convert-old-esx-scripts).

## Rolling back [#rolling-back]

If the update breaks something you cannot fix quickly:

1. Stop the server.
2. Restore the `resources` folder from your backup.
3. Restore the database from the dump: `mysql -u esx -p es_extended < esx_backup_2026-10-20.sql` into an empty database.
4. Start the server and confirm it works, then investigate the problem on a test server.

## Related [#related]

- [Troubleshooting](/docs/getting-started/troubleshooting)
- [Database schema](/docs/guides/database-schema)
- [Convert old ESX scripts](/docs/guides/convert-old-esx-scripts)
- [Manual installation](/docs/getting-started/manual-installation)
