How to Use the SQLite Module in AMX Mod X

April 22, 2026 Daemon666 8 min read 4 visualizações

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

SituationUse
One server, data local to itSQLite
Several servers sharing ranks/bansMySQL
A web panel reads the data liveMySQL
You want zero moving partsSQLite
Heavy concurrent writes from many processesMySQL

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 a sqlite3 shell open with an uncommitted transaction, or two game servers point at the same .sq3 file. One server, one file.
  • unable to open database filedata/sqlite/ does not exist, or is not writable by the HLDS user. Check with sudo -u steam touch data/sqlite/test.
  • Module failed to load — the .so is missing or is not 32-bit. See the module load fix.
  • no such table: points — the plugin queried before its CREATE TABLE callback completed. Threaded queries are asynchronous; chain the first read off the create callback rather than firing both from plugin_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 TABLE is missing IF NOT EXISTS and 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

  1. amxx modules lists SQLite as running.
  2. The .sq3 file appears in data/sqlite/ after the first map.
  3. sqlite3 file.sq3 ".tables" shows your plugin's tables.
  4. 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.

Colaboradores: Daemon666 ✦
Compartilhar: