QBox Framework Guide: Migrate from QBCore and Boost Performance (2026)
QBox has firmly established itself as the natural successor to QBCore in the FiveM roleplay ecosystem.

QBox has firmly established itself as the natural successor to QBCore in the FiveM roleplay ecosystem. If you are running a QBCore server in 2026 and wondering whether to make the switch, or if you are starting fresh and choosing between frameworks, this guide covers everything you need to know: real performance numbers, a step-by-step migration process, code-level conversion examples, and the pitfalls that trip up most server owners during the transition.
What Is QBox and Why Does It Exist

QBox (sometimes written as Qbox or qbx) is a FiveM roleplay framework built by former QBCore contributors who wanted to address the performance, security, and code quality issues that had accumulated in the original project. Rather than patching QBCore endlessly, they forked it and rebuilt the architecture around the Overextended (ox) ecosystem.
The result is a modular framework where qbx_core serves as the foundation, but heavy lifting is delegated to purpose-built libraries: ox_lib for utilities and UI, ox_inventory for item management, oxmysql for database operations, and ox_target for interaction targeting. This is not a monolithic framework. Each component can be updated independently without breaking the rest of your server.
QBox ships with several features built directly into qbx_core that previously required separate resources on QBCore: multicharacter selection, a server queue system, multijob and multigang support, and Discord Rich Presence. All of these are enabled by default and configurable through simple Lua config files.
Performance Benchmarks: QBox vs QBCore vs ESX
Performance claims without numbers are worthless, so let us look at actual benchmark data from the FiveM community in 2025-2026. These numbers come from controlled tests running identical server configurations with 64 players.
CPU Usage Comparison
| Framework | Core Resource CPU | Total Framework Overhead | Relative Performance |
|---|---|---|---|
| ESX Legacy | 0.01-0.02ms | ~0.30ms | Baseline (fastest) |
| QBox | 0.00-0.01ms | ~0.42ms | ~25% more than ESX |
| QBCore | 0.02-0.05ms | ~0.73ms | ~43% more than ESX |
Memory Usage
| Framework | Core Memory | With Inventory | Total Stack |
|---|---|---|---|
| ESX Legacy | ~18 MiB | ~25 MiB (qs-inventory) | ~45 MiB |
| QBox | ~22 MiB | ~30 MiB (ox_inventory) | ~55 MiB |
| QBCore | ~28 MiB | ~40 MiB (qb-inventory) | ~75 MiB |
What These Numbers Mean in Practice
ESX Legacy remains the raw performance champion. That has not changed in 2026. However, QBox closes the gap significantly compared to QBCore, using roughly 25-40% less CPU depending on the server load and script count. For most servers, the difference between ESX and QBox is imperceptible to players. The difference between QBCore and QBox, on the other hand, translates directly into better tick rates and smoother gameplay, especially on servers running 80+ resources.
QBox achieves these gains through several architectural decisions: lazy loading of modules, elimination of redundant polling loops that existed in QBCore, native use of ox_lib's optimized utility functions, and a cleaner event system that reduces unnecessary network traffic.
Pre-Migration Checklist
Before touching a single file on your production server, work through this checklist. Skipping any of these steps is the primary reason migrations fail.
- Full database backup -- dump your entire MySQL/MariaDB database. Not just the players table, everything. Use
mysqldump --all-databases > backup_$(date +%Y%m%d).sql - Full server file backup -- copy your entire resources folder, server.cfg, and any custom configuration files to an external location
- Set up a development server -- never migrate on production first. Clone your server to a test environment
- Document your current resource list -- run
refreshin the txAdmin console and export your resource list. Note which scripts are QBCore-native and which are third-party - Check script compatibility -- cross-reference your scripts against the compatibility table below
- Update to the latest QBCore first -- if you are on an old QBCore version, update to the latest release before migrating. This eliminates compounding issues
- Verify your database collation -- the
player.citizenidcolumn must useutf8mb4_unicode_cicollation. Check and change it if needed - Inform your development team -- staff familiar with QBCore events and exports will need time to learn Qbox and ox_lib idioms
Step-by-Step Migration from QBCore to QBox
Step 1: Install QBox via the txAdmin Recipe
The cleanest migration path uses the official txAdmin recipe. This downloads and configures all required files automatically: server.cfg, ox.cfg, permissions.cfg, and voice.cfg.
If you cannot use the recipe (for example, on a custom hosting setup), manually download qbx_core from the QBox GitHub repository and follow the configuration files in the txAdminRecipe repository.
Step 2: Install the Overextended Stack
Install the ox dependencies in this exact order, validating that each one starts without errors before moving to the next:
- oxmysql -- database driver (replaces mysql-async or ghmattimysql)
- ox_lib -- utility library (UI elements, callbacks, shared functions)
- ox_inventory -- inventory system (replaces qb-inventory)
- ox_target -- interaction targeting (replaces qb-target)
Your server.cfg resource start order should reflect this dependency chain:
ensure oxmysql
ensure ox_lib
ensure ox_inventory
ensure qbx_core
ensure ox_target
# ... your other resources below
Step 3: Configure ox_inventory for QBox
Add this convar to your server.cfg before the resource ensures:
setr inventory:framework "qbx"
Then run the ox_inventory database conversion script. This migrates your existing item data from qb-inventory's format to ox_inventory's format. Back up your database before this step. The conversion is documented in the ox_inventory documentation.
Step 4: Convert Job and Gang Grade Formats
This is the single most common source of errors during migration. In QBCore, job grades are stored as strings. In QBox, they are numbers.
QBCore format (jobs.lua):
['police'] = {
label = 'Law Enforcement',
grades = {
['0'] = { name = 'Recruit', payment = 500 },
['1'] = { name = 'Officer', payment = 750 },
['2'] = { name = 'Sergeant', payment = 1000 },
['3'] = { name = 'Lieutenant', payment = 1250 },
['4'] = { name = 'Chief', payment = 1500, isboss = true },
},
},
QBox format (jobs.lua):
['police'] = {
label = 'Law Enforcement',
grades = {
[0] = { name = 'Recruit', payment = 500 },
[1] = { name = 'Officer', payment = 750 },
[2] = { name = 'Sergeant', payment = 1000 },
[3] = { name = 'Lieutenant', payment = 1250 },
[4] = { name = 'Chief', payment = 1500, isboss = true },
},
},
The change is subtle but critical: ['0'] becomes [0], ['1'] becomes [1], and so on. Apply this to both qbx_core/shared/jobs.lua and qbx_core/shared/gangs.lua.
Step 5: Run the QBox SQL Migration
Execute the qbx_core.sql file included with qbx_core. This creates the additional database tables QBox needs, including tables for the multijob and multigang systems. If your player.citizenid column does not have utf8mb4_unicode_ci collation, fix that first or the SQL will fail.
Step 6: Configure Built-in Features
QBox bundles features that were separate resources on QBCore. Decide which ones you want:
-- qbx_core/config/client.lua
Config = {
useExternalCharacters = false, -- set true if using a separate multichar resource
-- Discord Rich Presence settings at bottom of file
}
-- server.cfg
setr qbx:enablequeue true # built-in queue system
setr qbx:max_jobs_per_player 1 # multijob limit (cannot be disabled)
setr qbx:max_gangs_per_player 1 # multigang limit (cannot be disabled)
Step 7: Test and Validate
Start your development server and systematically test each resource. Focus on:
- Player spawning and character selection
- Inventory operations (give, take, use items)
- Job actions and grade-based permissions
- Vehicle spawning and garage systems
- Banking and money transactions
- Phone functionality
Converting Scripts: Code-Level Examples
While QBox maintains approximately 99% backwards compatibility with QBCore scripts, converting your resources to use native QBox APIs improves performance and future-proofs your code. The core object (QBCore = exports['qb-core']:GetCoreObject()) no longer exists in QBox. Instead, you use exports and imported modules.
Updating Your fxmanifest.lua
First, add the QBox module imports to your script's manifest:
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
shared_scripts {
'@ox_lib/init.lua',
'@qbx_core/modules/lib.lua',
}
client_scripts {
'@qbx_core/modules/playerdata.lua',
'client/main.lua',
}
server_scripts {
'@oxmysql/lib/MySQL.lua',
'server/main.lua',
}
Common Function Replacements
Here is a practical before-and-after for a typical client script:
Before (QBCore):
local QBCore = exports['qb-core']:GetCoreObject()
RegisterNetEvent('myresource:client:doSomething', function()
local PlayerData = QBCore.Functions.GetPlayerData()
local job = PlayerData.job.name
local plate = QBCore.Functions.GetPlate(GetVehiclePedIsIn(PlayerPedId(), false))
if job == 'police' then
exports['qb-core']:DrawText('You are on duty', 'left')
Wait(3000)
exports['qb-core']:HideText()
end
end)
After (QBox):
RegisterNetEvent('myresource:client:doSomething', function()
local job = QBX.PlayerData.job.name
local plate = qbx.getVehiclePlate(GetVehiclePedIsIn(PlayerPedId(), false))
if job == 'police' then
lib.showTextUI('You are on duty', { position = 'left-center' })
Wait(3000)
lib.hideTextUI()
end
end)
Notice: no core object initialization, no exports call to get the core. QBX.PlayerData is available directly through the imported playerdata module, and qbx.getVehiclePlate() comes from the lib module.
Callback Migration
This is where most script conversions break. QBCore callbacks do not fire on QBox if you use the old registration pattern:
Before (QBCore):
-- Server
QBCore.Functions.CreateCallback('myresource:server:getData', function(source, cb)
local result = MySQL.query.await('SELECT * FROM my_table')
cb(result)
end)
-- Client
QBCore.Functions.TriggerCallback('myresource:server:getData', function(result)
print(json.encode(result))
end)
After (QBox / ox_lib):
-- Server
lib.callback.register('myresource:server:getData', function(source)
return MySQL.query.await('SELECT * FROM my_table')
end)
-- Client
local result = lib.callback.await('myresource:server:getData')
print(json.encode(result))
The ox_lib callback system is cleaner and eliminates the callback pyramid pattern. It uses await instead of nested callbacks, making your code significantly more readable.
Full Replacement Reference
| QBCore | QBox Equivalent |
|---|---|
QBCore.Functions.GetPlayerData() | QBX.PlayerData |
QBCore.Functions.GetPlate(vehicle) | qbx.getVehiclePlate(vehicle) |
QBCore.Shared.Jobs | exports.qbx_core:GetJobs() |
QBCore.Shared.Gangs | exports.qbx_core:GetGangs() |
QBCore.Shared.Vehicles | exports.qbx_core:GetVehiclesByName() |
QBCore.Shared.Weapons | exports.qbx_core:GetWeapons() |
QBCore.Shared.Items | exports.ox_inventory:Items() |
exports['qb-core']:DrawText() | lib.showTextUI() |
exports['qb-core']:HideText() | lib.hideTextUI() |
QBCore.Functions.CreateCallback | lib.callback.register |
QBCore.Functions.TriggerCallback | lib.callback.await |
Script Compatibility Table
Here is the current compatibility status of popular scripts with QBox as of March 2026:
| Script Category | Popular Scripts | QBox Status | Notes |
|---|---|---|---|
| Inventory | ox_inventory | Native | Default with QBox |
| Phone | qb-phone / lb-phone | Compatible | Works via bridge layer |
| Housing | qb-houses / bcs-housing | Compatible | Minor config changes |
| Vehicles | qb-vehicleshop | Compatible | Works without changes |
| Garages | qb-garages / jg-advancedgarages | Compatible | Works without changes |
| Banking | qb-banking / Renewed-Banking | Needs Update | Must adapt to ox_inventory money |
| Police | qb-policejob | Compatible | QBox has native replacement (qbx_policejob) |
| EMS | qb-ambulancejob | Compatible | QBox has native replacement (qbx_ambulancejob) |
| Mechanic | qb-mechanicjob | Compatible | Works via bridge layer |
| Crafting | qb-crafting | Needs Update | Must use ox_inventory crafting API |
| Target | ox_target | Native | Replaces qb-target |
| UI/TextUI | ox_lib | Native | Replaces qb-core DrawText |
| Multicharacter | Built into qbx_core | Native | No separate resource needed |
| Loading Screen | Custom | Compatible | Framework-independent |
| HUD | qb-hud / ps-hud | Compatible | Works without changes |
| Doorlock | ox_doorlock | Native | Replaces qb-doorlock |
Common Migration Pitfalls and How to Avoid Them
1. Job Grades as Strings Instead of Numbers
This is the number one migration error. If your scripts or database still reference job grades as strings ('0', '1'), things will break silently. Grade-based permission checks will fail, boss menus will not load, and job actions will be denied without clear error messages.
Fix: Search your entire resources folder for grade comparisons and ensure they use numbers. Check your database records too.
2. Callbacks That Never Return
If you migrate to QBox but keep scripts using QBCore.Functions.CreateCallback, those callbacks will hang indefinitely on the client side. The QBCore bridge does not fully replicate the old callback system.
Fix: Convert all callbacks to lib.callback.register and lib.callback.await from ox_lib.
3. Inventory Item Name Mismatches
ox_inventory uses a different item registration system than qb-inventory. Items defined in qb-core/shared/items.lua need to be registered in ox_inventory's items configuration instead.
Fix: Run the ox_inventory conversion tool and verify all item names match across your scripts.
4. Database Driver Conflicts
Running mysql-async alongside oxmysql causes connection pool conflicts and race conditions.
Fix: Remove mysql-async entirely. Replace all mysql-async calls with oxmysql's await API pattern.
5. Starting Resources in the Wrong Order
ox_lib must start before qbx_core. ox_inventory must start before most gameplay resources. Getting this wrong causes cascading nil reference errors.
Fix: Follow the exact resource start order outlined in Step 2 of the migration section above.
Should You Migrate in 2026?
The honest answer depends on your situation:
Migrate now if:
- You are starting a new server from scratch
- You are planning a major server overhaul anyway
- You are experiencing performance issues on QBCore with 60+ players
- Your development team wants modern tooling and cleaner APIs
Wait or skip if:
- Your server is stable, players are happy, and you have no performance complaints
- You rely heavily on scripts that deeply modify QBCore internals
- Your team does not have the bandwidth for testing and validation
For new servers in 2026, QBox is the clear recommendation. It offers better performance than QBCore, a modern developer experience through the ox ecosystem, and active maintenance from a dedicated team. The backwards compatibility layer means you are not locked out of the massive QBCore script ecosystem, and the migration path is well-documented.
If you want to explore the framework comparison in more depth, check out our QBox vs QBCore comparison or dive into the complete QBox and Ox stack guide for the full picture of how the Overextended ecosystem fits together.
For servers looking to stock up on compatible scripts, browse our FiveM script collection -- we test all scripts for QBox compatibility and label them accordingly.
Frequently Asked Questions
Is QBox backwards compatible with QBCore scripts?
Yes, QBox maintains backwards compatibility with most QBCore resources through its compatibility layer. However, some scripts that deeply hook into QBCore internals may need minor adjustments.
How much faster is QBox than QBCore?
Based on community benchmarks, QBox with ox_lib typically uses 25-40% less CPU than a comparable QBCore setup. ESX Legacy still edges out both in raw performance, but QBox offers better developer experience and modern tooling.
Should I migrate my existing QBCore server to QBox?
If your server is stable and players are happy, there's no urgent need. But for new servers or planned overhauls, QBox is the recommended choice in 2026 due to better performance, ox_inventory by default, and active development.
How long does QBox migration take?
For a typical QBCore server with 30-50 scripts, expect 2-4 days for the core migration and testing. Most QBCore scripts work without changes, but inventory and banking scripts may need updates for ox_inventory compatibility.
