FiveM & QBCore · Practical guide

How to Add a Garbage Job to Your QBCore FiveM Server

A garbage collection job is one of the most popular starter jobs on FiveM. Players drive a truck, pick up bins and earn money. This guide covers setting it up on QBCore.

Stellar AI · Updated 8 September 2026 · 7 min read

A practical guide to how to add a garbage job to your qbcore fivem server, with implementation decisions, validation steps, and security considerations for a production-minded project.

Overview

This guide shows how to add a robust, secure garbage job to a QBCore FiveM server. It covers architecture, data modeling, server-side validation, client interactions, implementation choices (QBCore/ESX/ox_lib), testing, deployment and ongoing maintenance. The example emphasizes server authority: never trust client input. For designers using companion tooling or analytics, consider integrating external workflows such as the Stellar AI platform via https://trystellarai.com/app to prototype routes or asset placement, but keep runtime validation on your server.

Goals and requirements

  • Create a job that players can start from a job center or phone.
  • Provide route generation and a garbage truck vehicle with persistent job state stored server-side.
  • Validate every collection/payout on the server and write reliable database updates.
  • Support ox_lib / qb-target / qb-menu integrations for modern UI and targeting.
  • Be testable locally and deployable with clear migration and maintenance steps.

High-level architecture

Design the system so the server is authoritative for job state, money, and inventory changes. The client should only render UI, play sounds/animations, and send intent (e.g., "I attempted to pick up bag id 123"). The server verifies the request, checks cooldowns, route ownership, and item counts, then updates the database and emits confirmation events back to the client.

Components:

  • Server module: job registration, route manager, state persistence, payout logic.
  • Database: tables for player job progress, truck assignments, route definitions, payouts.
  • Client module: UI, marker/blip rendering, interaction handlers, animations.
  • Optional integrations: ox_lib for menus, qb-target for interactions, oxmysql/ghmattimysql for DB.

Data model and persistence

Keep the model minimal but complete. Example tables/objects:

  • garbage_routes (route_id, route_points JSON, payout_base)
  • garbage_jobs (player_id, job_active boolean, route_id, progress JSON, truck_plate, last_update)
  • garbage_logs (log_id, player_id, action, value, timestamp)

Store route progress and bag ownership server-side as a small JSON blob to avoid inconsistent client state. Always update through single atomic DB operations where possible (use transactions or a single UPDATE statement). For oxmysql you can use execute with parameterized queries; for ghmattimysql use the execute/async helpers your server provides.

Server-side implementation (QBCore example)

Key principles:

  • Validate player job status, proximity to a bag, and truck assignment before accepting a collection request.
  • Rate-limit collection calls and log suspicious behavior.
  • Perform all money and item adjustments on the server and persist them immediately.
-- server/main.lua (simplified)
local QBCore = exports['qb-core']:GetCoreObject()

-- Secure handler: client requests to collect a bag
RegisterNetEvent('garbage:server:collectBag', function(bagId)
  local src = source
  local Player = QBCore.Functions.GetPlayer(src)
  if not Player then return end

  -- Fetch job state from DB or in-memory cache
  local jobState = GetPlayerGarbageJob(Player.PlayerData.citizenid)
  if not jobState or not jobState.job_active then
    -- reject - player is not on the job
    TriggerClientEvent('garbage:client:collectRejected', src, 'not_on_job')
    return
  end

  -- Server-side proximity and legitimacy check:
  if not ValidateBagOwnership(jobState, bagId) then
    -- potential cheat attempt: do not trust client claims
    LogSuspicious(src, 'invalid_bag_collect', bagId)
    return
  end

  -- Calculate payout securely on server
  local payout = CalculatePayoutForBag(jobState.route_id)
  -- Update DB atomically, increment progress, and give payout
  if UpdateJobProgressAndPayout(Player.PlayerData.citizenid, bagId, payout) then
    Player.Functions.AddMoney('cash', payout, 'garbage-collection')
    TriggerClientEvent('garbage:client:collectSuccess', src, bagId, payout)
  else
    TriggerClientEvent('garbage:client:collectRejected', src, 'db_fail')
  end
end)

Server-side DB update pattern

Use parameterized SQL queries and wrap multi-statement changes in a transaction when possible. If using oxmysql, use exports.oxmysql:execute and handle errors. Always handle DB failures gracefully and inform the client of the server-side state.

Client-side implementation

The client should:

  • Display route: blips and markers based on server-sent route points.
  • Send intention events to the server (e.g., TriggerServerEvent('garbage:server:collectBag', bagId)).
  • Listen for server confirmation events and update local state/UI only after confirmation.

Never award money or items on the client. Show temporary animations and "pending" UI if you want instant feedback, but mark them as tentative until the server confirms.

-- client/main.lua (simplified)
RegisterNetEvent('garbage:client:updateRoute', function(routeData)
  -- draw blips & markers; do NOT trust client-only route as authority
  RenderRoute(routeData)
end)

-- player interacts with bag
function OnInteractWithBag(bagId)
  -- play pickup animation, then request server authorization
  TriggerServerEvent('garbage:server:collectBag', bagId)
end

RegisterNetEvent('garbage:client:collectSuccess', function(bagId, payout)
  -- show UI and update local progress
  ShowPayoutNotification(payout)
end)

Integration choices: ox_lib, qb-target, ESX considerations

Modern FiveM setups often use ox_lib for menus and utilities, and qb-target for interaction targeting. Use these to present a clean player experience, but maintain the same server-authoritative flow.

  • ox_lib: use its menus and progress bars for non-authoritative UI. All state changes must still originate from server validation.
  • qb-target / ox_target: use target zones to offer "Collect" interactions. Trigger server events only on interaction confirmation.
  • ESX servers: replace QBCore function calls with ESX equivalents. Keep server validation patterns identical.

Security and anti-cheat considerations

Never trust the client. Specific measures:

  • Validate position on the server where possible. If you must rely on client-provided coordinates, verify these against the server’s expected route points and a reasonable distance threshold.
  • Rate limit critical events per player and per truck to avoid spamming exploits.
  • Log and review suspicious patterns: many different bag IDs collected in rapid succession, large payouts without DB updates, or requests from players without an active job.
  • Do not accept client-side inventory changes; always check with the canonical server inventory.

Testing and debugging

Test locally before deploying. Recommended steps:

  1. Run a local server with minimal resources and a test database snapshot.
  2. Simulate normal job flows and edge cases: disconnect mid-route, DB failure during payout, duplicate bag collects.
  3. Enable verbose server logs for job events and DB queries when debugging, then reduce verbosity in production.
  4. Test third-party integration points (oxmysql, ghmattimysql) by intentionally failing the DB to see fallback behavior.

Use txAdmin or your preferred FiveM manager to monitor resource CPU and script errors during load testing. For behavior-driven tests, write small scripts that simulate many clients collecting on the same route to ensure race conditions are handled.

Deployment and maintenance

Deploy with migrations and rollback capability. Checklist before pushing updates:

StepActionWho/When
DB MigrationApply new table/schema changes using versioned migration scriptsDB Admin / Deploy
BackupCreate a backup snapshot of production DBOps / Before deploy
ConfigVerify oxmysql/ghmattimysql connection strings and credentialsDev/Ops
Smoke TestStart server in staging and run the job end-to-endQA
MonitorEnable logs and quick rollback if anomalies detectedOps / 24h after deploy

Maintain: rotate logs, review payout economics periodically, and watch for new exploit patterns. Keep libraries (QBCore, ox_lib, qb-target) up to date and read their release notes for breaking changes.

Roblox notes (Luau, if recreating similar job on Roblox)

Roblox servers must also be authoritative. Use RemoteEvents only to send intents from client to server; all validation, awarding of in-game currency and DataStore writes must happen server-side. Patterns to follow:

  • Use RemoteEvents to request actions, but validate player position/time/cooldowns on the server.
  • When using DataStore, always use pcall() to handle service outages and implement exponential backoff or fallback queues to avoid data loss.
  • Test DataStore failure modes in a controlled environment: queue saves locally in memory and drain the queue once DataStore recovers.
  • Use ServerScriptService for authoritative logic and avoid trusting any client modifications.

Practical checklist

ItemPass/FailNotes
Server validates every collection__Check event handlers and logs
DB updates are atomic__Test concurrent collects
Client only renders UI__Ensure no client money adds
Rate limits present__Throttle high-frequency calls
Backup and migration scripts ready__Versioned SQL scripts
Monitoring and alerts configured__Log suspicious patterns

Performance considerations

Large servers require efficient event handling and minimal DB churn. Suggestions:

  • Cache job state in memory and flush to DB periodically or on important transitions rather than on every minor action; still persist critical events (payouts) immediately.
  • Batch non-critical writes and use background workers to process logs or analytics.
  • Avoid sending large route payloads on every tick — push route once and send incremental updates only when required.

Further reading and tools

For route prototyping or job analytics, teams sometimes leverage AI-assisted workflows during development. See the Stellar AI platform for research and experimentation: https://trystellarai.com/app. For blog-style writeups and community best practices, see https://trystellarai.com/blog.

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 →