FiveM Docs
Guides

Database Schema

Every ESX Legacy database table explained with columns, types, keys and the resources that use them, from users and jobs to billing, banking and owned_vehicles.

ESX Legacy stores all persistent data in a MySQL or MariaDB database accessed through oxmysql. The complete schema lives in [SQL]/legacy.sql in esx_core, and each core resource and addon ships its own .sql file with the tables it needs. This page lists every table, its columns and which resource reads or writes it.

How the schema is created

There are three ways tables end up in your database:

  1. legacy.sql: the full schema with seed data (jobs, items, vehicles, fines). txAdmin's ESX recipe imports it for you.
  2. Per-resource .sql files: for example esx_billing.sql or esx_identity.sql. Useful if you install resources one by one.
  3. Automatic migrations: since 1.16.0, es_extended loads the SQL catalog from esx_lib on startup. It creates missing tables, adds missing columns and inserts missing seed rows for es_extended and the official resources (identity, multicharacter, skin, addonaccount, billing, banking, garage, jobs and more). It records what it did in esx_catalog_imports. Several addons (esx_billing, esx_banking, esx_garage, esx_addonaccount, esx_license, esx_whitelist, esx_property) also run their own migrations.

Seed rows are only inserted when missing

The catalog inserts a seed row only if no row with the same key exists (jobs.name, job_grades (job_name, grade), items.name and so on). It does not overwrite your own changes to labels or salaries.

Core tables (es_extended)

users

One row per character. Created by es_extended; several resources add columns.

ColumnTypeDefaultAdded byNotes
identifiervarchar(60)nonees_extendedPrimary key. License without prefix, or char<N>:<license> with multicharacter
ssnvarchar(11)nonees_extendedUnique (unique_ssn). Generated per character, read with xPlayer.getSSN()
accountslongtextNULLes_extendedJSON object of account name to balance
groupvarchar(50)'user'es_extendedPermission group, see Admin permissions
inventorylongtextNULLes_extendedJSON of item name to count (default inventory)
jobvarchar(20)'unemployed'es_extendedMust match jobs.name
job_gradeint(11)0es_extendedMust match job_grades.grade
loadoutlongtextNULLes_extendedJSON weapons list (default inventory)
metadatalongtextNULLes_extendedJSON, read with xPlayer.getMeta()
positionlongtextNULLes_extendedJSON coords and heading
firstname, lastnamevarchar(16)NULLesx_identity
dateofbirthvarchar(10)NULLesx_identity
sexvarchar(1)NULLesx_identitym or f
heightint(11)NULLesx_identity
skinlongtextNULLesx_skinJSON skinchanger data
statuslongtextNULLesx_statusHunger, thirst and other statuses
is_deadtinyint(1)0esx_ambulancejob / esx_deathUsed when Config.SaveDeathStatus is on
death_timebigintNULLesx_deathAdded by esx_death.sql
idint(11)auto incrementlegacy.sqlUnique key id
disabledtinyint(1)0esx_multicharacterDisabled character slots
last_propertylongtextNULLesx_propertyLast property the player was in
created_attimestampCURRENT_TIMESTAMPlegacy.sql
last_seentimestampNULL, ON UPDATE CURRENT_TIMESTAMPlegacy.sqlUpdated whenever the row changes
phone_numbervarchar(20)NULLlegacy.sqlNot read by es_extended; available for phone resources
pincodeintNULLesx_bankingATM PIN

Example accounts value with the default Config.Accounts:

{ "bank": 50000, "money": 0, "black_money": 0 }

jobs

ColumnTypeDefaultNotes
namevarchar(50)nonePrimary key, used in users.job and xPlayer.setJob()
labelvarchar(50)NULLDisplay name
typevarchar(50)'civ'Job type, filter with ESX.GetJobs(type). Seeds use civ, leo, ems, mechanic
whitelistedtinyint(1)0Used by esx_joblisting to hide jobs from the job center

job_grades

ColumnTypeDefaultNotes
idint(11)auto incrementPrimary key
job_namevarchar(50)NULLReferences jobs.name (no foreign key)
gradeint(11)noneGrade number, starting at 0
namevarchar(50)noneInternal grade name. boss grants the society boss menu by default
labelvarchar(50)noneDisplay name
salaryint(11)nonePaycheck amount per Config.PaycheckInterval
skin_male, skin_femalelongtextnoneJSON uniform, '{}' if unused. Written by the esx_society uniform manager

A job without any grade is ignored by ESX.RefreshJobs() with a warning. See Create a job.

items

ColumnTypeDefaultNotes
namevarchar(50)nonePrimary key
labelvarchar(50)noneDisplay name
weightint(11)1Counted against Config.MaxWeight
raretinyint(4)0Stored and sent to the client; no core gameplay effect
can_removetinyint(4)10 blocks dropping and giving the item

Not used when ox_inventory runs; items then come from ox_inventory/data/items.lua. See Add items.

owned_vehicles

Created by esx_vehicleshop.sql and legacy.sql; extended by esx_garage. Used by es_extended (extended vehicles), esx_garage, esx_vehicleshop, esx_policejob, esx_lscustom, esx_boat, esx_property and others.

ColumnTypeDefaultAdded byNotes
ownervarchar(60)NULLcoreusers.identifier. Indexed
platevarchar(12)nonecorePrimary key
vehiclelongtextNULLcoreJSON vehicle properties
typevarchar(20)'car'corecar, boat, aircraft...
jobvarchar(20)NULLcoreSet for job vehicles
storedtinyint(4)0core1 = in a garage
parkingvarchar(60)NULLesx_garageGarage the vehicle is parked in
poundvarchar(60)NULLesx_garageImpound location
custom_namevarchar(50)NULLesx_garagePlayer-chosen name
is_favoritetinyint(1)0esx_garage
last_usedintNULLesx_garage
mileagedecimal(10,2)0.00esx_garage

esx_garage also creates composite indexes such as idx_owned_vehicles_owner_plate and idx_owned_vehicles_owner_stored_pound_plate, and tracks its schema version in esx_garage_migrations.

esx_catalog_imports

Created by the esx_lib SQL catalog.

ColumnTypeNotes
resourcevarchar(64)Primary key, resource whose seed data was prepared
versionvarchar(32)Catalog version, for example 1.16.0
localevarchar(32)Locale used for seeded labels
updated_attimestamp

Character and identity tables

multicharacter_slots

Used by esx_multicharacter to give individual players more character slots.

ColumnTypeNotes
identifiervarchar(60)Primary key, license without the char prefix
slotsint(11)Number of slots. Indexed

whitelist

ColumnTypeNotes
identifiervarchar(60)Primary key

This table is still in legacy.sql, but the current esx_whitelist resource uses the two tables below instead.

esx_whitelist_config and esx_whitelist_identifiers

Created by esx_whitelist (whitelist.sql or automatically on start).

TableColumnTypeNotes
esx_whitelist_configsetting_keyvarchar(64)Primary key
setting_valuelongtext
updated_attimestampAuto-updated
esx_whitelist_identifiersidentifiervarchar(128)Primary key with type
typevarchar(32)Default 'whitelist', indexed
created_attimestamp

Society and shared data tables

addon_account and addon_account_data

Used by esx_addonaccount, esx_society (society money) and esx_vehicleshop. Society accounts are named society_<job>.

TableColumnTypeNotes
addon_accountnamevarchar(60)Primary key, e.g. society_police
labelvarchar(100)
sharedint(11)1 = one account for everyone (society), 0 = one per player
addon_account_dataidint(11)Primary key, auto increment
account_namevarchar(100)Indexed
moneyint(11)Balance
ownervarchar(60)NULL for shared accounts, identifier otherwise. Indexed

Unique key (account_name, owner). The 2026-10-02 hardening adds a generated owner_key column (COALESCE(owner, '')) with a unique key, so shared accounts cannot be duplicated either.

addon_inventory and addon_inventory_items

Used by esx_addoninventory for society and property stashes (default inventory).

TableColumnTypeNotes
addon_inventorynamevarchar(60)Primary key
labelvarchar(100)
sharedint(11)Shared or per player
addon_inventory_itemsidint(11)Primary key, auto increment
inventory_namevarchar(100)Indexed
namevarchar(100)Item name
countint(11)
ownervarchar(60)NULL for shared. Indexed

datastore and datastore_data

Generic JSON storage, used by esx_datastore, esx_accessories (user_mask, user_helmet...), esx_property and society resources.

TableColumnTypeNotes
datastorenamevarchar(60)Primary key
labelvarchar(100)
sharedint(11)
datastore_dataidint(11)Primary key, auto increment
namevarchar(60)Datastore name
ownervarchar(60)Indexed
datalongtextJSON

Unique key (name, owner).

society_moneywash

Used by esx_society for money washing.

ColumnTypeNotes
idint(11)Primary key, auto increment
identifiervarchar(60)Indexed
societyvarchar(60)
amountint(11)

Current esx_society also creates society_moneywash_operations (operation_id primary key, identifier, society, amount, state, created_at) on start and moves pending rows from society_moneywash into it.

Economy tables

billing

Used by esx_billing (and jobs that send bills).

ColumnTypeNotes
idint(11)Primary key, auto increment
identifiervarchar(60)Player who must pay. Indexed
sendervarchar(60)Identifier of the sender
target_typevarchar(50)player or society
targetvarchar(60)Receiving identifier or society account
labelvarchar(255)
amountint(11)

billing_payments

Created by esx_billing on start (and by the hardening script). It is a payment journal that makes paying a bill idempotent.

ColumnTypeNotes
bill_idintPrimary key
operation_idvarchar(64)Unique
identifier, sendervarchar(60)
target_typevarchar(10)
targetvarchar(100)
labelvarchar(255)
amountint
payment_accountvarchar(20)Account used to pay
stateenum('claimed','applied')Default claimed
created_at, applied_attimestamp

Rows stuck in claimed should be inspected manually. The hardening script explicitly says not to replay or refund them automatically.

banking

Transaction history for esx_banking.

ColumnTypeNotes
IDint(11)Primary key, auto increment
identifiervarchar(46) in legacy.sqlesx_banking widens it to varchar(60) on start
typevarchar(50)Deposit, withdraw, transfer...
amountint(64)
timebigint(20)Unix time in ms
balanceint(11)Balance after the transaction
labelvarchar(255)

Keys: idx_banking_identifier_time (identifier, time) and idx_banking_time (time).

fine_types

Fine catalog for esx_policejob.

ColumnTypeNotes
idintPrimary key, auto increment
labelvarchar(255)
amountint
categoryintGroups fines in the police fine menu. Seed data uses 0 (traffic) to 3 (most severe)

License tables

Used by esx_license, and through it by esx_dmvschool, esx_weaponshop, esx_boat and esx_drugs.

TableColumnTypeNotes
licensestypevarchar(60)Primary key, e.g. dmv, drive, weapon
labelvarchar(60)
user_licensesidint(11)Primary key, auto increment
typevarchar(60)License type
ownervarchar(60)Identifier

Unique key uq_user_licenses_owner_type (owner, type) so a player cannot hold the same license twice.

Vehicle shop tables

All used by esx_vehicleshop (vehicles is also read by esx_lscustom).

TableColumnsNotes
vehiclesname varchar(60), model varchar(60) (PK), price int(11), category varchar(60)Vehicles for sale
vehicle_categoriesname varchar(60) (PK), label varchar(60)Shop categories
cardealer_vehiclesid int(11) (PK), vehicle varchar(255), price int(11)Car dealer job stock
vehicle_soldid int(11) (PK), client, model, plate, soldby, date (all varchar(50))Sales log of the car dealer job
rented_vehiclesvehicle varchar(60), plate varchar(12) (PK), player_name varchar(255), base_price int, rent_price int, owner varchar(60)Rentals

esx_vehicleshop also creates vehicle_rental_payments (plate, billing_date as primary key, owner, amount, operation_id unique, state) on start.

Other tables created by addons

TableCreated byPurpose
esx_garage_migrationsesx_garageApplied garage schema migrations (name, version, applied_at)
esx_propertiesesx_propertyProperty definitions as JSON (id, data)
esx_property_migrationsesx_propertyApplied property migrations
bansesx_adminmenuBans with identifier, reason, banned_by, expires_at
admin_logsesx_adminmenuAdmin action log (actor, target, action, payload)

Inspecting your own database

-- Which catalog imports ran
SELECT * FROM esx_catalog_imports;

-- Jobs that have no grades (ignored by ESX)
SELECT j.name FROM jobs j
LEFT JOIN job_grades g ON g.job_name = j.name
WHERE g.id IS NULL;

-- Players whose job no longer exists (reset to unemployed on load)
SELECT identifier, job FROM users
WHERE job NOT IN (SELECT name FROM jobs);

Common issues

  • Unknown column 'ssn' on old databases: start es_extended 1.16 once, its migration adds and fills users.ssn. It stops if duplicate SSNs exist.
  • "Economy tables must use InnoDB": convert billing, users and addon_account_data with ALTER TABLE ... ENGINE=InnoDB after a backup.
  • Duplicate key errors in the hardening script: you have duplicate user_licenses or addon_account_data rows. Reconcile them by hand; the script never deletes financial rows.
  • Editing JSON columns while the server runs: online players are kept in memory and overwrite your change on the next save. Edit offline players only, or use in-game commands.

Frequently asked questions

Independent documentation

esx-fivem.com is a community project and is not affiliated with the ESX Framework team. Facts on this page were checked against the upstream source. Official resources: docs.esx-framework.org and github.com/esx-framework.
Edit on GitHub

Last updated on

On this page