The SQLite module gives AMX Mod X a real SQL database with no server, no credentials, and no network. It uses the same sqlx API as MySQL, so the same plugin code works against either backend — only the connection tuple changes. For a single game server that needs to persist points, ranks, shop purchases or settings, SQLite is often the correct choice and MySQL is over-engineering.
When SQLite is the right call
| Situation | Use |
|---|---|
| One server, data local to it | SQLite |
| Several servers sharing ranks/bans | MySQL |
| A web panel reads the data live | MySQL |
| You want zero moving parts | SQLite |
| Heavy concurrent writes from many processes | MySQL |
SQLite is also a strictly better choice than nvault for anything structured. nVault is a flat key/value store with no queries and a well-earned reputation for corruption; see nVault corruption.
1. Enable the module
addons/amxmodx/configs/modules.ini:
fun engine fakemeta cstrike csx hamsandwich sqlite
Check the file is there and is 32-bit:
ls -la /home/steam/hlds/cstrike/addons/amxmodx/modules/sqlite_amxx_i386.so file /home/steam/hlds/cstrike/addons/amxmodx/modules/sqlite_amxx_i386.so
You do not need to install SQLite on the host. The module carries its own engine. Restart the server — modules load at startup, not on map change.
2. Where the database file lives
The SQLite module puts databases under:
cstrike/addons/amxmodx/data/sqlite/
The directory must exist and must be writable by the user running HLDS. If it is not, every query fails and — depending on the plugin — you get silence, not an error.
mkdir -p /home/steam/hlds/cstrike/addons/amxmodx/data/sqlite chown -R steam:steam /home/steam/hlds/cstrike/addons/amxmodx/data chmod 755 /home/steam/hlds/cstrike/addons/amxmodx/data/sqlite
3. Connect from a plugin
Same sqlx API as MySQL. The only difference is the tuple: for SQLite the "database" is the file name and the host/user/pass are ignored.
#include <amxmodx>
#include <sqlx>
new Handle:g_tuple
public plugin_init()
{
register_plugin("SQLite Example", "1.0", "you")
// For SQLite the 4th argument is the database file (created if absent)
g_tuple = SQL_MakeDbTuple("", "", "", "server_stats")
SQL_ThreadQuery(g_tuple, "OnTableReady",
"CREATE TABLE IF NOT EXISTS points ( \
steamid TEXT PRIMARY KEY, \
name TEXT, \
points INTEGER DEFAULT 0 \
)")
}
public OnTableReady(failstate, Handle:query, error[], errnum, data[], size, Float:queuetime)
{
if (failstate != TQUERY_SUCCESS)
log_amx("SQLite error %d: %s", errnum, error)
}
Set amx_sql_type to sqlite in configs/sql.cfg if you use a plugin that reads the backend from there:
amx_sql_type "sqlite" amx_sql_db "server_stats"
That produces data/sqlite/server_stats.sq3.
4. Writing rows safely
Always escape values that come from a player. Names contain quotes, semicolons and worse, and SQLite is as injectable as MySQL:
new name[64], escaped[128], steamid[35], q[256]
get_user_name(id, name, charsmax(name))
get_user_authid(id, steamid, charsmax(steamid))
SQL_QuoteString(Empty_Handle, escaped, charsmax(escaped), name)
formatex(q, charsmax(q),
"INSERT OR REPLACE INTO points (steamid, name, points) VALUES ('%s', '%s', %d)",
steamid, escaped, points)
SQL_ThreadQuery(g_tuple, "OnSaved", q)
INSERT OR REPLACE is SQLite's upsert; MySQL uses ON DUPLICATE KEY UPDATE. This is the one place the two backends genuinely differ in a plugin, and it is why "SQLite and MySQL are drop-in interchangeable" is only 95% true.
5. Inspecting the database
Install the sqlite3 CLI on the host (this is for you, not for the module):
sudo apt install -y sqlite3 cd /home/steam/hlds/cstrike/addons/amxmodx/data/sqlite sqlite3 server_stats.sq3 sqlite> .tables sqlite> SELECT * FROM points ORDER BY points DESC LIMIT 10; sqlite> .quit
Do not run write queries against the file while the server is running. SQLite locks the whole database on write, and a long external transaction will make the game server's queries fail.
Common errors
database is locked— two writers. Usually you left asqlite3shell open with an uncommitted transaction, or two game servers point at the same.sq3file. One server, one file.unable to open database file—data/sqlite/does not exist, or is not writable by the HLDS user. Check withsudo -u steam touch data/sqlite/test.Module failed to load— the.sois missing or is not 32-bit. See the module load fix.no such table: points— the plugin queried before itsCREATE TABLEcallback completed. Threaded queries are asynchronous; chain the first read off the create callback rather than firing both fromplugin_init().- Data disappears after a restart — you are writing to a path inside a container without a volume, or the file is being recreated because the plugin's
CREATE TABLEis missingIF NOT EXISTSand failing silently.
Backups
The whole database is one file, which is the best thing about SQLite:
sqlite3 server_stats.sq3 ".backup '/home/steam/backups/stats-$(date +%F).sq3'"
Use .backup, not cp — copying a file that is being written produces a corrupt database. Put that in cron.
Verification
amxx moduleslists SQLite asrunning.- The
.sq3file appears indata/sqlite/after the first map. sqlite3 file.sq3 ".tables"shows your plugin's tables.- A value written in-game survives a map change and a full restart.
If you later outgrow one server, the same plugin code moves to the MySQL module with a different tuple and an upsert rewrite.









