FiveM & QBCore · Practical guide

How to Set Up a FiveM QBCore Server From Scratch

Complete beginner guide to setting up a FiveM QBCore roleplay server. Hosting, framework install, resources and first scripts explained.

Stellar AI · Updated 8 September 2026 · 6 min read

A practical guide to how to set up a fivem qbcore server from scratch, with implementation decisions, validation steps, and security considerations for a production-minded project.

This guide gives a complete, practical walkthrough to set up a FiveM server running QBCore from scratch, with architecture decisions, security and validation best practices, implementation notes covering QBCore/ESX/ox_lib integrations, Roblox parallels for server authority and DataStore handling, testing, deployment, and maintenance. Use this as a reference checklist and implementation template rather than a drop-in script. Always keep server authority and validation central: client input must be treated as untrusted on FiveM, and Roblox scripts must respect server-side validation and robust DataStore handling.

High-level architecture and resource layout

Design the server in layers: core framework (QBCore/ESX), shared utilities (ox_lib, utility resources), gameplay resources (jobs, inventory, vehicles), and infrastructure resources (database connector, logging, permissions). Keep resource boundaries clear so you can restart or replace modules without touching unrelated systems.

  • Core: qb-core or ESX base resource, event exporters, server callbacks.
  • Database: oxmysql or ghmattimysql / mysql-async adapter resource that mediates access to MySQL.
  • Libraries: ox_lib for menus/exports, ox_inventory or qb-inventory for item handling.
  • Gameplay modules: job scripts, vehicle spawning handlers, police utils, stores.
  • Admin tools: txAdmin, webadmin, rcon/logging export.

Example minimal fxmanifest pattern for a resource:

fx_version 'cerulean'
game 'gta5'

author 'you'
description 'example-job'
version '1.0.0'

shared_scripts {
  '@qb-core/shared/locale.lua',
  'config.lua'
}

server_scripts {
  '@oxmysql/lib/MySQL.lua', -- or ghmattimysql
  'server/main.lua'
}

client_scripts {
  'client/main.lua'
}

Database design and migrations

Use normalized tables for inventories, characters, vehicles, and permissions. Migrations should be versioned and idempotent. Use parameterized queries always; never construct SQL with direct concatenation of client-sent strings.

  • Tables: players, characters, items, vehicles, logs, sessions.
  • Indexes: add indexes on frequently queried columns (identifier, citizenid, job).
  • Migrations: store a schema_version table and write migrations that can be re-run safely.

Security and server validation

Security is a combination of architecture, code discipline, and runtime defense. For FiveM, treat all client-originated data as untrusted and perform full server-side validation for every sensitive action. In Roblox, authority must be on the server for state changes; clients are only requesters.

  • Never trust client input: validate item IDs, quantities, funds, and ownership on the server before committing anything.
  • Use parameterized queries: protect against SQL injection by using the DB library placeholders (oxmysql/ghmattimysql supplies parameter support).
  • Permissions and roles: store permission levels server-side and verify before privileged actions.
  • Rate-limiting and anti-spam: throttle repeated actions (e.g., pickup, buy) per player session.
  • Data integrity: use transactions for multi-step DB writes where supported.

Server-side validation example (QBCore server-side Lua):

-- server/main.lua
QBCore = exports['qb-core']:GetCoreObject()

RegisterNetEvent('shop:buyItem', function(itemId, amount)
  local src = source
  local Player = QBCore.Functions.GetPlayer(src)
  if not Player then return end

  -- Validate amount type and bounds
  if type(amount) ~= 'number' or amount < 1 or amount > 100 then
    -- invalid, ignore and log
    return
  end

  -- Validate item exists in server-side config
  local itemDef = ServerItemConfig[itemId]
  if not itemDef then return end

  local totalPrice = itemDef.price * amount
  if Player.PlayerData.money['bank'] < totalPrice then
    return -- insufficient funds
  end

  -- Final server-side transaction
  Player.Functions.RemoveMoney('bank', totalPrice)
  Player.Functions.AddItem(itemId, amount)
end)

Implementation choices: QBCore vs ESX and ox_lib

QBCore and ESX are different design philosophies. QBCore favors lightweight modularity and exports; ESX is more monolithic historically. Choose based on resource compatibility and team familiarity. ox_lib provides client-side UI and server exports that many modern resources rely on—treat it as a library dependency with clear version control and update strategy.

  • Prefer QBCore if you want modular exports and a modern flow (server callbacks and player wrappers).
  • Choose ESX if you must use legacy resources unless you plan to convert them incrementally.
  • Use ox_lib for menus, notifications, and easier client-server utility exports, but keep all authoritative logic on the server.

Inventory and item systems

Pick an inventory system (ox_inventory, qb-inventory) that matches your persistence model. For stackable items, enforce server-side stacking rules and size limits. Apply anti-duplication checks on item creation and transfers.

Roblox parallels: server authority, RemoteEvents, and DataStore failure handling

Roblox development shares many of the same central principles: the server must be authoritative, RemoteEvents/RemoteFunctions are transport only, and DataStore operations must gracefully handle failures and rate limits.

  • Server authority: do all state mutations on server scripts. Use client requests only to initiate actions. Never allow the client to alter critical state directly.
  • RemoteEvent pattern: client -> server: validate parameters and permissions; server -> client: send sanitized view-only state.
  • DataStore reliability: implement retry with exponential backoff, use UpdateAsync carefully, and use BindToClose to persist data on shutdown.

Roblox DataStore retry example (Luau):

local DataStoreService = game:GetService('DataStoreService')
local PlayersStore = DataStoreService:GetDataStore('Players')

local function savePlayerData(userId, data)
  local retries = 0
  local success, err
  repeat
    success, err = pcall(function()
      PlayersStore:UpdateAsync(tostring(userId), function(old)
        return data
      end)
    end)
    if not success then
      retries += 1
      task.wait(2 ^ math.min(retries, 5)) -- exponential backoff capped
    end
  until success or retries >= 5
  if not success then
    warn('Failed saving for', userId, err)
  end
end

Testing, debugging, and QA

Test at multiple levels: unit tests for pure logic where possible, integration tests for DB interactions, and load tests for connection and session behaviors. Use txAdmin and cfx.re console logs for runtime issues. Create local staging environments that mirror production MySQL and resource ordering.

  • Automated tests: validate business logic functions (Lua unit tests via busted if applicable).
  • Integration tests: simulate player sequences for login, purchases, vehicle spawns.
  • Load testing: use bots or scripted clients to simulate connection spikes and resource restarts.
  • Runtime debugging: use dbg prints, structured JSON logs, and txAdmin live console for crash traces.

Deployment and maintenance

Deploy with reproducible builds and versioned resources. Use CI to push resource artifacts and a robust restart strategy to minimize downtime. Back up databases and automated snapshots daily, and keep schema migrations backward-compatible when possible.

Tools and best practices:

  • Use Git for all resources and tag releases.
  • Use txAdmin for process management, auto-restarts, and scheduled backups.
  • Automate database backups with retention policies and test restores regularly.
  • Document upgrade steps and perform blue-green deploys when touching core database changes.

For hands-on deployment dashboards and workspace integration, consider using the Stellar AI tools: https://trystellarai.com/app for project organization. Integrate server logs and monitoring into your deployment pipeline and keep an eye on critical error rates; coordinating tools can help — check https://trystellarai.com/app for workflow options and the team blog at https://trystellarai.com/blog for operational guides.

Monitoring, logging, and incident response

Structured logs and error aggregation are essential. Log important security events (failed validation, suspicious actions). Use tags to filter per-player or per-resource problems, and keep an incident playbook for rollbacks and hotfixes.

  • Log levels: debug, info, warn, error. Send error/warn to an aggregator.
  • Alerting: set alerts on high error rates, repeated validation failures, and long DB queries.
  • Incident playbook: immediate mute/ban steps, how to roll back a migration, and emergency restart scripts.

Practical checklist

Task Why Completed
Install QBCore / base Provides player abstractions, callbacks, and core exports [ ]
Set up MySQL + oxmysql Persistent storage with safe parameterized queries [ ]
Implement server-side validation Prevents duplication, fraud, and exploits [ ]
Configure txAdmin and backups Process management and automated backups [ ]
Test resource restart/resilience Ensure safe hot-reloads and dependency ordering [ ]
Monitor logs & alerts Early detection of regressions or abuse [ ]

Maintenance and upgrades

Keep a scheduled maintenance window for upgrades. Always run migrations against a clone of production first. Keep a changelog and rollback steps published to your team. For third-party libraries like ox_lib, track upstream releases and test them in staging before deploying to production.

Build your next system with Stellar AI

Describe one feature, get organized project files, then bring back your errors to keep improving. Start free with no card required. Test generated code in a private development environment before release.

Create your first script free →