FiveM & QBCore · Practical guide

How to Migrate From ESX to QBCore on Your FiveM Server

Switching from ESX to QBCore is a big step but worth it. This guide covers the key differences, what to migrate, and how to convert your existing scripts.

Stellar AI · Updated 8 September 2026 · 7 min read

A practical guide to how to migrate from esx to qbcore on your fivem server, with implementation decisions, validation steps, and security considerations for a production-minded project.

Introduction

This guide walks a server operator through migrating a FiveM server from ESX to QBCore with emphasis on architecture, security, implementation choices, testing, and safe deployment. It assumes you maintain production players and want to minimize downtime while preserving player data and gameplay behavior. The migration strategy below favors incremental, reversible steps and strict server-side validation. If you need tooling or a control dashboard during migration, consider external tools or platforms that integrate with your workflow; see the Stellar AI app for project management and tracking: https://trystellarai.com/app.

Architecture Differences: ESX vs QBCore

Understanding the core architectural differences helps you decide how to map resources and APIs.

  • Player object and functions: ESX exposes xPlayer and exported functions; QBCore exposes player objects via QBCore.Functions.GetPlayer and a callback system (QBCore.Functions.CreateCallback). QBCore tends to centralize functionality under QBCore.Functions and uses standardized events and exports.
  • Database layer: Both setups use MySQL (oxmysql/ghmattimysql/mysql-async). Modern QBCore installs commonly use oxmysql and pair well with ox_lib utilities.
  • Libraries: QBCore servers commonly include ox_lib for UI and utility features; ESX servers historically use different helper resources. Expect to replace or adapt client-side UI code to work with ox_lib or native qb-target / qb-menu patterns.
  • Resource naming: QBCore organizes core resources (qb-core, qb-banking, qb-inventory). Plan namespace changes and ensure no conflicting resource names.

Planning the Migration

Establish a migration plan with prioritized items: player persistence, economy (money, bank), jobs, inventory, vehicles, and third-party scripts (garages, jobs, shops).

  1. Inventory current resources and dependencies: list ESX scripts, their versions, and what DB tables they use.
  2. Back up your full database and resource folder (including .sql dumps and resource zips).
  3. Choose a migration strategy: big-bang replacement, staged conversion, or adapter/wrapper layer.
  4. Set up a staging server that mirrors production but with a copy of the database. Never test on live without a rollback plan.

Data Migration: Mapping Schemas and Ensuring Integrity

Data is the most critical piece. Use an explicit mapping table to convert ESX schema to QBCore equivalents and validate identifiers.

ESX Table/Concept QBCore Equivalent Migration Action
users / users table (money, bank) players or player tables in qb-core Map money fields to player financial properties; migrate using an explicit UPDATE or insert to qb_core players table. Ensure identifier fields (license, steam) match.
owned_vehicles player_vehicles or qb-vehicles Convert vehicle JSON schemas and ensure plate collisions are handled. Verify ownership queries after import.
inventory (esx_inventory) qb-inventory or ox_inventory Normalize item identifiers and quantity fields. Test stack limits and weight if used.
job assignments qb-core job system Map ESX job names and grades to QBCore job entries. Update DB rows to reflect new job identifiers.

Tips:

  • Perform a dry-run import into a staging DB and run integrity checks (count mismatches, missing identifiers).
  • Preserve old player identifiers in a migration table to allow rollback.
  • Keep transactions atomic where multiple tables must change simultaneously. Use SQL transactions via oxmysql where available.

Implementation Choices: Strategies and Patterns

There are three common approaches to actually replacing ESX with QBCore:

  1. Adapter/Compatibility Layer — create lightweight server-side shims that implement ESX exports using QBCore internals. This allows 3rd-party ESX scripts to keep functioning temporarily while you convert them. Use this for low-risk, low-traffic servers where immediate behavior parity is required.
  2. Gradual Resource Conversion — convert scripts in priority order (e.g., economy first, then jobs, then misc resources). Use feature flags and turn resources off/on per job to test in isolation.
  3. Full Replacement — deploy qb-core and converted resources in a maintenance window. Require more planning but faster completion.

Server validation code example (FiveM / QBCore): never trust client inputs — always validate server-side.

RegisterServerEvent('myshop:buyItem')
AddEventHandler('myshop:buyItem', function(itemName, amount)
  local src = source
  local xPlayer = QBCore.Functions.GetPlayer(src)
  if not xPlayer then return end

  -- Server-side lookup for item price and availability
  local itemDef = Config.ShopItems[itemName]
  if not itemDef then return end

  local price = itemDef.price * tonumber(amount or 1)
  -- Validate player can afford the purchase on server
  if xPlayer.PlayerData.money.cash >= price then
    -- Deduct and grant item server-side
    xPlayer.Functions.RemoveMoney('cash', price)
    xPlayer.Functions.AddItem(itemName, tonumber(amount))
    TriggerClientEvent('QBCore:Notify', src, 'Purchase complete', 'success')
  else
    TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds', 'error')
  end
end)

Key patterns:

  • Resolve item metadata on the server; do not accept client-side price or ID fields.
  • Use QBCore.Functions.GetPlayer and manipulate PlayerData only server-side.
  • Use callbacks for synchronous client-server queries when needed (QBCore.Functions.CreateCallback).

Security and Server Validation

Security is critical during and after migration. Follow these rules:

  • Never trust client input. Always revalidate items, quantities, and prices on the server.
  • Use server-side rate limiting for expensive operations (e.g., item spawns, bank transfers) and enforce per-player cooldowns.
  • Validate identifiers (license, steam) present in DB rows when reconciling migrated data. Ensure no duplicates or mismatches that could cause account takeover.
  • Secure remote calls: prefer server callbacks or exports rather than raw RegisterNetEvent handlers without validation.
  • Plan for rollback: keep migration scripts reversible by storing original rows in a migration log table.

Testing and QA

Testing should cover functional, integration, and security tests. Set up test cases that simulate typical player flows and edge cases.

  • Automated script test: spawn players, perform common actions, assert DB state changes.
  • Manual QA: enlist a small group of trusted players to validate economy and jobs on a staging server.
  • Security test: attempt invalid client payloads and verify server rejects them consistently.

Practical migration checklist (use this during each resource conversion):

Step Action Pass Criteria
Backup Export DB and resource files Complete dump verified on separate machine
Staging Import Import data to staging DB No integrity errors; user counts match
Adapter Test Run ESX script against QBCore adapter Script functions as expected in staging
Functional QA Perform transactions and job actions All flows complete and DB consistent
Security Check Test invalid client inputs Server rejects invalid requests and logs attempts

Deployment and Rollout Strategies

Minimize player disruption by using careful rollout techniques.

  • Blue/Green or Staged Rollout: Run QBCore on a copy of the server, redirect a subset of players to test, then switch traffic after monitoring.
  • Feature flags: Toggle new functionality on only for testing accounts before enabling globally.
  • Maintenance window: For a full replacement, schedule a window and notify players in advance. Ensure backups are accessible and that rollback scripts are ready.

After deployment, continue monitoring logs for unexpected validation failures and re-run migration scripts if any data mismatches appear. For extra observability, you can integrate external dashboards; one option that teams use to coordinate deployment tasks and track issues is the Stellar AI platform: https://trystellarai.com/app.

Maintenance and Future-Proofing

After migration, lock in practices that keep the server healthy and easier to maintain:

  • Keep QBCore and ox_lib up to date and follow changelogs before upgrading production. Test upgrades in staging first.
  • Document any adapters or compatibility layers you created; these are technical debt and should be prioritized for eventual removal.
  • Standardize server-side validation helpers and centralize them where possible so future resources reuse secure patterns.
  • Keep a migration log table that records migrations, scripts run, and their checksums to audit later.

For further reading on operational best practices and community updates, see the project blog: https://trystellarai.com/blog.

Roblox-Specific Considerations (If Relevant)

If your team also develops for Roblox, apply similar server-authority principles. A few concrete rules:

  • Server Authority: All game state changes must be applied on the server. Do not perform authoritative state updates from client scripts.
  • RemoteEvents & RemoteFunctions: Use RemoteEvents or RemoteFunctions for client-server communication. Validate every request on the server. Example handler:
local Remote = game.ReplicatedStorage:WaitForChild("PurchaseEvent")
Remote.OnServerEvent:Connect(function(player, itemId, amount)
  -- Validate types and player state
  if typeof(itemId) ~= "string" or typeof(amount) ~= "number" then return end
  -- Validate item exists on server
  local itemDef = itemConfig[itemId]
  if not itemDef then return end
  -- Validate currency, deduct server-side, then grant
  local leaderstats = player:FindFirstChild("leaderstats")
  if leaderstats and leaderstats.Cash.Value >= itemDef.price * amount then
    leaderstats.Cash.Value = leaderstats.Cash.Value - itemDef.price * amount
    -- grant item server-side
  end
end)

DataStore Failure Handling: Always use pcall for datastore operations and implement retries with backoff. Never assume GetAsync/UpdateAsync will always succeed. Example pattern:

local function safeGet(datastore, key)
  local attempts = 0
  while attempts <= 5 do
    local ok, result = pcall(function()
      return datastore:GetAsync(key)
    end)
    if ok then
      return true, result
    end
    attempts = attempts + 1
    wait(2 ^ attempts * 0.1) -- exponential backoff
  end
  return false, nil
end

Monitoring, Logging, and Incident Response

After the migration, set up monitoring for key signals: unexpected money spikes, rapid inventory changes, or repeated validation errors. Log rejected client payloads with context (player id, offending payload, server-side rule triggered) to diagnose attempted exploits. Maintain a simple incident playbook and ensure backups exist before any emergency fix is applied.

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 →