Every serious FiveM server needs a database. Player inventories, vehicles, properties, bank accounts, job history - all of it lives in SQL. MariaDB is the community standard, and setting it up correctly makes the difference between a server that scales and one that chokes at 50 players.
Why MariaDB Over MySQL
MariaDB is a drop-in replacement for MySQL with better performance for the types of queries FiveM generates. It uses less memory, handles concurrent connections better, and is completely free.
For FiveM specifically:
- Faster SELECT queries on player data lookups
- Better handling of simultaneous INSERT operations (when 64 players save simultaneously)
- Lower memory footprint (important when running alongside the FiveM server)
Installation and Configuration
On Linux:
apt install mariadb-server
mysql_secure_installation
Create a database and user for your FiveM server:
CREATE DATABASE fivem_server;
CREATE USER 'fivem'@'localhost' IDENTIFIED BY 'strong_password_here';
GRANT ALL PRIVILEGES ON fivem_server.* TO 'fivem'@'localhost';
FLUSH PRIVILEGES;
MariaDB Configuration for FiveM
Edit /etc/mysql/mariadb.conf.d/50-server.cnf:
[mysqld]
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
max_connections = 150
query_cache_type = 1
query_cache_size = 64M
tmp_table_size = 64M
max_heap_table_size = 64M
The innodb_buffer_pool_size should be about 50-70% of dedicated database RAM. For a FiveM server, 1GB is typically enough.
Connection String
In your FiveM server config:
set mysql_connection_string "mysql://fivem:password@localhost/fivem_server?waitForConnections=true&connectionLimit=50"
The connectionLimit controls how many simultaneous database connections your server can open. 50 is safe for most servers. High-pop servers (100+) may need 75-100.
Common Performance Issues
| Problem | Symptom | Fix | |---------|---------|-----| | Slow player loading | 5+ second join times | Add indexes to player lookup columns | | Lag spikes every minute | Server freezes briefly | Move saves to async queries | | Database growing too large | Disk filling up | Clean old character data, archive logs | | Connection timeouts | Random script errors | Increase connectionLimit |
Adding Indexes
The single biggest performance improvement. If your scripts look up players by identifier:
CREATE INDEX idx_identifier ON players(identifier);
CREATE INDEX idx_citizenid ON players(citizenid);
Without indexes, every player lookup scans the entire table. With indexes, lookups are instant regardless of table size.
Async vs Sync Queries
Sync queries block the server thread until the result returns. The entire server freezes until the query completes. Never use sync queries for anything that happens during gameplay.
Async queries run in the background and call a callback when done. The server continues processing normally.
-- BAD: Blocks server
local result = MySQL.query.await('SELECT * FROM players WHERE identifier = ?', {identifier})
-- GOOD: Non-blocking
MySQL.query('SELECT * FROM players WHERE identifier = ?', {identifier}, function(result)
-- Handle result
end)
On Space-Node FiveM hosting, the NVMe SSD ensures database reads complete in microseconds rather than milliseconds, making even suboptimal queries tolerable. But proper async design is still essential for smooth gameplay at scale.
