What the database actually does on a FiveM server
A FiveM server keeps two kinds of state. The game state lives in memory while the server runs and disappears on restart. Persistent state, the things players expect to still exist tomorrow, lives in a database. Characters, money, inventories, vehicles, properties, and player permissions are all rows in tables. Without a working database, frameworks like ESX, QBCore, and qbx_core will not load, and players cannot save anything.
FiveM does not talk to MySQL directly. A resource sits between your Lua code and the database engine and translates queries. The current standard for that job is oxmysql, maintained by the Overextended team. It replaced the older mysql-async and ghmattimysql resources, and almost every modern framework and script expects it. This guide installs the database engine, creates the database, wires up oxmysql, and walks through the errors that stop a server from booting.
Step 1: Install MariaDB or MySQL
MariaDB and MySQL are compatible for FiveM's purposes. MariaDB is the common choice because it is free, fast, and ships in most server panels. Pick one. Do not install both on the same machine, because they compete for port 3306.
On Windows, download the MariaDB MSI installer from mariadb.org/download. During setup it asks for a root password. Write that password down, because you will need it to create your server's database and user. The installer also lets you enable "Use UTF8 as default server's character set," which you should leave on so player names with special characters store correctly.
On a Linux VPS running Ubuntu or Debian, install with the package manager:
sudo apt update
sudo apt install mariadb-server
sudo mysql_secure_installation
The mysql_secure_installation script sets the root password, removes anonymous users, and drops the test database. Run it. After install, confirm the service is up with sudo systemctl status mariadb.
Step 2: Create a database and a dedicated user
Never run your FiveM server as the MySQL root user. Create a database for the server and a user with rights only to that database. This limits damage if a script is compromised and keeps your connection string out of the all-powerful root account.
Open the SQL shell. On Linux that is sudo mysql. On Windows, open the "MySQL Client" or "MariaDB Command Prompt" from the Start menu and log in with your root password. Then run:
CREATE DATABASE fivem CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'fivem'@'localhost' IDENTIFIED BY 'a-strong-password-here';
GRANT ALL PRIVILEGES ON fivem.* TO 'fivem'@'localhost';
FLUSH PRIVILEGES;
The utf8mb4 character set matters. The older utf8 in MySQL only stores three bytes per character and breaks on emoji and some names. Use utf8mb4 everywhere.
If your database and your FiveM server run on different machines, change 'localhost' to the server's IP or '%' for any host, and make sure port 3306 is open in the firewall. For a single-box setup, keep localhost. It is faster and safer.
A GUI makes this easier
Most server owners manage the database with a graphical tool instead of the command line. HeidiSQL ships with the MariaDB Windows installer and is the standard on Windows. phpMyAdmin is the web-based equivalent common on managed hosting and game panels like txAdmin's host. Both let you create databases, run SQL files, and browse tables. You will use one of them in Step 5 to import schemas.
Step 3: Add the oxmysql resource
Download the latest release from github.com/overextended/oxmysql. Take the release build from the Releases page, not a copy of the source repository, because the release includes the compiled files the resource needs.
Unzip it into your resources folder. Rename the folder to exactly oxmysql with no version suffix, so the path is resources/[standalone]/oxmysql or wherever you keep standalone resources. The folder name must match the resource name your other scripts reference.
Step 4: Set the connection string in server.cfg
oxmysql reads its connection details from a single convar in your server.cfg. There are two valid formats. The URI format is the modern recommendation:
set mysql_connection_string "mysql://fivem:a-strong-password-here@localhost/fivem"
The semicolon format also works and is easier to read when a password contains special characters:
set mysql_connection_string "server=localhost;uid=fivem;password=a-strong-password-here;database=fivem"
The pieces map directly to what you created in Step 2: the user is fivem, the password is what you set, the host is localhost, and the database is fivem. If your MySQL runs on a non-standard port, add it, for example localhost:3307 in the URI form or port=3307 in the semicolon form.
Now the ordering rule that trips up almost everyone. oxmysql must start before any resource that queries the database. In server.cfg, put ensure oxmysql above ensure es_extended, ensure qb-core, or ensure qbx_core. If a framework starts first, it tries to query a database connection that does not exist yet and throws errors.
ensure oxmysql
ensure es_extended
Keep the connection string out of any file you push to a public Git repository. It contains your database password.
Step 5: Import your framework's .sql schema
An empty database has no tables. Each framework ships one or more .sql files that create the tables it needs. ESX ships an [core].sql or per-resource SQL files, QBCore ships a qbcore.sql, and individual scripts often include their own .sql in the resource folder.
In HeidiSQL, select your fivem database in the left panel, open the File menu, choose "Load SQL file," pick the framework's .sql, then press F9 or the run button to execute it. In phpMyAdmin, select the database, click the Import tab, choose the file, and press Go. After importing, refresh and confirm tables like users, players, or owned_vehicles appear.
Import order can matter when scripts depend on each other. Import the framework core first, then resource-specific SQL. If a file fails partway, read the error: a missing table usually means you imported in the wrong order, and a duplicate key means part of it already ran.
Step 6: Connection pooling and performance
oxmysql manages a connection pool for you. Instead of opening a new connection for every query, it keeps a set of open connections and reuses them, which is far faster under load. The default pool size is fine for most servers. You can raise it by adding a connectionLimit parameter to the connection string, for example ?connectionLimit=10 on the URI form, but the more common tuning convar is set mysql_slow_query_warning 150, which logs any query slower than 150 milliseconds so you can find the script that is hammering the database. Slow queries, not pool size, are what usually cause database lag on a busy server.
Verifying it works
Start the server and watch the console. oxmysql prints a line confirming it connected, including the database name and the MariaDB or MySQL version. If you see that line and your framework loads without database errors, you are done. Join the server, create a character, restart the server, and confirm the character is still there. That round trip proves persistence works.