WELCOME coupon available Use code WELCOME at checkout through July 31, 2026. WELCOME

How to Evaluate, Test, and Maintain FiveM Scripts

Testing a free script?

Free scripts are fine for quick checks. For production servers, compare full server packs or maintained paid scripts by framework and use case.

This no-fluff guide how to maintain FiveM scripts is for server owners, developers, and QA leads. You’ll get a production-like “Test City” in Docker, an acceptance checklist you can run end-to-end, a quantitative risk scoring model, and a vendor-vetting rubric that keeps you away from headaches.

TL;DR

  • Spin up Test City (Docker) to isolate and benchmark any script safely.
  • Run the Acceptance Checklist before a penny changes hands.
  • Use the Risk Score (0–100) to decide ship/hold/reject.
  • Vet sellers with the Vendor Rubric (don’t skip this).
  • If you buy, prefer reputable stores — see our picks: Best Tebex Shops.

Part 1 — “Test City” (Docker) for Safe, Repeatable Script QA

What you get

  • Containerized FXServer + MariaDB (+ Adminer)
  • Clean server.cfg with oxmysql and base resources
  • Bind-mounted resources/custom where you drop the script under test
  • Deterministic network names/ports for simple DB strings

Download test-city.zip (Github)

How to use:

  1. Unzip → cd test-city
  2. Copy .env.example to .env and set your LICENSE_KEY (and DB creds if you like).
  3. Drop oxmysql into server-data/resources/[standalone]/oxmysql/.
  4. Put the script under test into server-data/resources/custom/<scriptname>/ and add ensure <scriptname> to server.cfg.
  5. docker compose build && docker compose up -d → connect via Direct Connect to localhost:30120.

Prereqs: Docker + Docker Compose, a cfx license key, and an oxmysql resource copy (drop into server-data/resources/[standalone]/oxmysql).

Folder layout

test-city/
├─ docker-compose.yml
├─ fxserver/
│  ├─ Dockerfile
│  └─ entrypoint.sh
├─ server-data/
│  ├─ server.cfg
│  └─ resources/
│     ├─ [standalone]/oxmysql/   # place oxmysql here
│     └─ custom/                 # put the script under test here (e.g., myscript/)
└─ .env

.env (example)

LICENSE_KEY=changeme_cfx_license_key
MYSQL_DATABASE=fivem
MYSQL_USER=fivem
MYSQL_PASSWORD=fivempw
MYSQL_ROOT_PASSWORD=rootpw
FX_ARTIFACT_URL=https://runtime.fivem.net/artifacts/fivem/build_proot_linux/master/LATEST.tar.xz
# Tip: replace with a specific artifact URL you trust for reproducibility.

docker-compose.yml

version: "3.9"

networks:
  testcity:

volumes:
  db_data:

services:
  db:
    image: mariadb:10.11
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    command: >
      --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
      --innodb_buffer_pool_size=256M
    volumes:
      - db_data:/var/lib/mysql
    networks: [testcity]

  adminer:
    image: adminer:4
    restart: unless-stopped
    ports:
      - "8080:8080"
    networks: [testcity]
    depends_on: [db]

  fxserver:
    build:
      context: ./fxserver
      args:
        FX_ARTIFACT_URL: ${FX_ARTIFACT_URL}
    restart: unless-stopped
    environment:
      LICENSE_KEY: ${LICENSE_KEY}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    depends_on: [db]
    networks: [testcity]
    ports:
      - "30120:30120/udp"
      - "30120:30120/tcp"
      - "40120:40120/tcp" # txAdmin (optional)
    volumes:
      - ./server-data:/opt/fivem/server-data

fxserver/Dockerfile

FROM debian:bookworm-slim

ARG FX_ARTIFACT_URL
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends 
    xz-utils curl ca-certificates tini bash && 
    rm -rf /var/lib/apt/lists/*

# Fetch & extract FXServer artifact (URL provided via build-arg)
RUN mkdir -p /opt/fivem && 
    curl -fsSL "$FX_ARTIFACT_URL" -o /opt/fivem/fx.tar.xz && 
    tar -xJf /opt/fivem/fx.tar.xz -C /opt/fivem && 
    rm -f /opt/fivem/fx.tar.xz

# Non-root
RUN useradd -ms /bin/bash fivem
USER fivem

WORKDIR /opt/fivem
COPY --chown=fivem:fivem ../server-data /opt/fivem/server-data
COPY --chown=fivem:fivem entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/usr/bin/tini","--"]
CMD ["/bin/bash","/entrypoint.sh"]

fxserver/entrypoint.sh

#!/usr/bin/env bash
set -euo pipefail

# Provide DB string for oxmysql via server.cfg (already set there),
# just ensure the DB is reachable before boot to avoid spam errors.
echo "Waiting for database..."
until nc -z db 3306; do sleep 1; done
echo "DB ready."

# Run FXServer with our server.cfg
# Most Linux artifacts ship a run.sh in the artifact root.
exec bash /opt/fivem/run.sh +exec /opt/fivem/server-data/server.cfg

If your artifact uses a different launcher path, adjust the last line accordingly (e.g., /opt/fivem/alpine/opt/cfx-server/run.sh).

server-data/server.cfg (lean, test-ready)

# ---------- Identity ----------
sv_licenseKey "%LICENSE_KEY%"            # injected by env in entrypoint command or replace manually
sv_hostname "Test City — Script QA"
sets tags "qa,testing,fivemx"
sv_maxclients 2
onesync on
sv_scriptHookAllowed 0
sv_enforceGameBuild 3095

# ---------- Networking ----------
endpoint_add_tcp "0.0.0.0:30120"
endpoint_add_udp "0.0.0.0:30120"

# ---------- Database (oxmysql) ----------
set mysql_connection_string "mysql://%MYSQL_USER%:%MYSQL_PASSWORD%@db:3306/%MYSQL_DATABASE%?charset=utf8mb4"

# ---------- Core / Base resources ----------
ensure mapmanager
ensure chat
ensure spawnmanager
ensure sessionmanager
ensure hardcap
ensure baseevents

# ---------- Datastore ----------
ensure oxmysql

# ---------- Under test ----------
# Drop your script folder into resources/custom/<scriptname> and enable here:
# ensure myscript

# ---------- QA helpers ----------
# Verbose logging in dev
setr con_minSeverity info

# Enable txAdmin panel (optional)
setr txAdminPort 40120

Enable your script: copy it into server-data/resources/custom/myscript/ and add ensure myscript to the bottom block.

Run it

cd test-city
docker compose build
docker compose up -d
# Adminer at http://localhost:8080 (server: db, user: fivem, pass: fivempw)
# Connect FiveM client → Direct Connect: your-docker-host:30120

Part 2 — Script Acceptance Checklist (Do Not Skip)

Use this every time. Copy into your tracker and check off items.

A. Pre-flight (before install)

  • Source type: Open source / partially open / escrow-only.
  • Dependencies listed: framework (ESX/QBCore/QBOX), ox_lib, oxmysql, PolyZone, etc.
  • fxmanifest.lua: lua54 'yes', correct game 'gta5', fx_version not ancient.
  • Docs: install steps, config examples, permissions, locales, known conflicts.
  • License/ToS: usage rights, refund policy, updates, support channel.

B. Installability

  • No console errors on ensure: zero stack traces or asset missing spam.
  • No deprecated natives spam.
  • Config loads clean: no JSON/Lua syntax errors.
  • DB migrations: create tables once; re-starts don’t re-apply or break.

C. Functional

  • Core flows work: happy path tested (e.g., purchase, job flow, crafting).
  • Edge cases: wrong inputs, missing perms, out-of-range quantities.
  • Localization: no hard-coded strings if locales promised.
  • Permissions: staff/admin commands gated; no free access client-side.

D. Performance (client & server)

E. Security

  • Server-side validation: every server event validates source, perms, and input types.
  • No trust in client: money/inventory changes only from server logic.
  • No eval/loadstring/remote code patterns.
  • Anti-abuse: rate limits/throttles on spammy endpoints.
  • Escrow integrity: no backdoors in non-escrow config loaders.

Good event pattern (example):

RegisterNetEvent('myscript:buy', function(item, amount)
  local src = source
  if type(item) ~= 'string' or type(amount) ~= 'number' or amount < 1 then return end
  if not HasPermission(src, 'shop.buy') then return end
  local xPlayer = GetPlayer(src) -- framework adapter
  if not xPlayer then return end
  -- validate price server-side, check inventory limits, do DB in a transaction
end)

F. Compatibility & Cleanliness

  • Framework adapters present (ESX/QBCore/QBOX) or clearly declared unsupported.
  • No globals leakage, unique event names, no resource name assumptions.
  • Uninstall clean: removing the resource doesn’t break others.

Part 3 — Quantitative Risk Scoring Model (0–100)

Use this to decide “ship/hold/reject.” Lower is better.

FactorWeightHow to Score (0=good → 5=bad)
Performance0.20resmon idle: 0=≤0.10ms, 1=≤0.20, 3=≤0.50, 5=>0.50; spikes add +1
Security0.250=all server-validated + rate limits; 3=some gaps; 5=trusts client / unsafe events
Stability0.150=no errors; 3=occasional warnings; 5=frequent errors/hitches
Compatibility0.100=adapters/tests; 3=one framework only; 5=breaks common deps
Maintainability0.100=docs/changelog/semantic versions; 5=no docs/abandoned
Supply-chain/Vendor0.200=reputable, history, refunds; 5=unknown, no policy

Formula

RiskScore = 100 * Σ(weight_i * (score_i / 5))

Bands & Actions

  • 0–24 (Low): Ship to staging, monitor.
  • 25–49 (Moderate): Fixes required before live.
  • 50–74 (High): Hold; request vendor patches or replace.
  • 75–100 (Critical): Reject.

Example

  • Perf=1, Sec=3, Stability=1, Compat=1, Maint=2, Vendor=1
  • Risk = 100*(.2*.2 + .25*.6 + .15*.2 + .1*.2 + .1*.4 + .2*.2) = 34 → Moderate

Part 4 — Vendor Vetting Rubric (score each 0–5, higher is better)

CriterionWhat “Good” Looks LikeNotes
Identity & Track RecordClear brand, years active, consistent handleAvoid burner stores
DocumentationInstall + config + perms + troubleshootingScreenshots/gifs help
Update CadenceChangelog, semantic versions, recent commits/releasesQuarterly+ is fine
Support QualityTicket/Discord SLAs, reproducible fixes, not just “restart”Sample responses
Issue TransparencyPublic known issues & roadmapHonesty > perfection
Refund/ToS ClarityRefund window, conditions, license termsNo dark patterns
Testing ProofStaging video, perf metrics, framework listEven better: demo server
Security HygieneMentions server-side checks, no sensitive keys, no evalAsk about audits
Compatibility PolicyESX/QBCore/QBOX stated, adapters, version matrixState supported builds
Pricing & ValueFair for complexity, no dependency paywallsWatch upsell traps

Rubric Score (0–50):

  • 40–50: Strong — preferred vendor
  • 30–39: Acceptable — monitor
  • 20–29: Weak — proceed cautiously
  • <20: Avoid

Pro tip: Cross-reference with reputable marketplaces. Start here: Best Tebex Shops.


Part 5 — Maintenance Playbook (After You Ship)

  1. Version pinning: lock script releases + dependency versions (e.g., oxmysql, ox_lib).
  2. Staging first: all updates land in Test City; run the acceptance checklist again.
  3. Backups & rollback: DB snapshot + resource files before each update. Keep a Rollback.md with exact steps.
  4. CI smoke test (optional, recommended): headless client connect + command macro to hit main flows; parse server console for errors.
  5. Operational metrics: keep a simple ledger per script: average resmon (idle/active), error count/session, incident notes.
  6. Changelog discipline: require vendor changelogs; maintain your own integration notes.
  7. De-risk scheduled events: update outside peak hours; announce maintenance windows.

Part 6 — Templates You Can Copy

A. Test Plan (per script)

# Script Test Plan — <name> <version>

## Context
Framework(s): ESX/QBCore/QBOX
Dependencies: oxmysql vX, ox_lib vY, PolyZone vZ
DB Migrations: yes/no
Escrow: yes/no

## Functional Cases
- [ ] Case 1:
- [ ] Case 2:
- [ ] Negative 1:

## Performance
resmon idle: ____ ms
resmon active: ____ ms (scenario: ______)

## Security Checks
- [ ] All server events validate source/perm/input
- [ ] Rate limits present
- [ ] No client-trusted money/inventory mutations

## Logs & Errors
Paste snippet (server + F8): 

## Result
Pass/Fail + Notes

B. Rollback.md (skeleton)

# Rollback — <date> <script> <from→to>

1) Disable script: `stop <resource>`
2) Restore resource files from backup: <path>
3) Restore DB snapshot: <path/command>
4) Restart FXServer
5) Verify: console clean, perf normal, flows ok

C. Issue Template

**Summary**
What happened vs expected, with timestamps.

**Repro Steps**
1) ...
2) ...

**Env**
Artifact build:
Framework & versions:
Script version:
Other deps:

**Logs**
Server console:
F8:

**Attachments**
Screens/video if possible.

How to Use This Guide Efficiently

  1. Bootstrap Test City once, keep it clean.
  2. For each candidate script:
    • Drop into resources/custom/, enable in server.cfg.
    • Run the Acceptance Checklist.
    • Compute the Risk Score.
    • Vet the seller with the Vendor Rubric.
  3. If it passes, merge into staging; if not, request fixes or walk away.

Need more testing guides? Check out the section

Luke
Luke

I'm Luke, I am a gamer and love to write about FiveM, GTA, and roleplay. I run a roleplay community and have about 10 years of experience in administering servers.

Articles: 436