FiveM & QBCore · Practical guide

How to Set Up a Death and Respawn System on FiveM QBCore

A proper death system stops instant respawning and forces players to wait for EMS or bleed out. This guide covers configuring the QBCore death and respawn system.

Stellar AI · Updated 8 September 2026 · 7 min read

A practical guide to how to set up a death and respawn system on fivem qbcore, with implementation decisions, validation steps, and security considerations for a production-minded project.

Overview and goals

This guide walks you through designing and implementing a robust death and respawn system for FiveM using QBCore. It focuses on architecture, server-side validation, practical implementation patterns, alternatives for ESX and ox_lib, and complementary notes for Roblox/Luau developers who need to replicate safe patterns. The goal is to deliver a server-authoritative system that prevents client-side tampering, supports revive mechanics, logs important events, and is maintainable in production.

If you want a compact project planner and asset tracker to manage your script deployment, consider using the Stellar AI app for project coordination and SEO tasks: try the app.

Architecture overview

A death/respawn system must separate responsibilities between server and client. The server is authoritative for state (isDead, lastDeathTime, bleedout, respawnLocation, inventory state). The client is responsible for presentation: animations, UI, control locks, and attempting to trigger server events. Never rely on client assertions of death without server-side verification layers.

Core components:

  • Server state manager: stores death metadata in player persistent storage or runtime memory and validates actions like revive or respawn.
  • Client visual layer: shows downed screen, countdown timers, and local effects; sends server events to request actions.
  • Revive providers: player-based revive, EMS job revives, or auto-respawn after timeout.
  • Logging & analytics: audit death events for debugging and abuse detection.

Server-side design (QBCore)

The server must enforce rules: who can revive, whether inventory is dropped on death, cooldowns, and DB persistence. Use QBCore's player management to get player instances and update metadata. Typical server event flow:

  1. Client signals possible death: TriggerServerEvent('death:client:requestDeath')
  2. Server receives event; uses source (server-provided) to find the player and perform validation checks.
  3. If validated, server marks player as dead in metadata and triggers client to enter downed state (TriggerClientEvent).
  4. Revive attempts are server-validated and update metadata/DB when successful; respawn is authorized by server.

Example server handler (Lua)

RegisterNetEvent('death:server:requestDeath')
AddEventHandler('death:server:requestDeath', function(clientReportedState)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    -- Never trust clientReportedState blindly. Use it only as a hint.
    -- Additional server validation should be performed.
    local lastDeath = Player.PlayerData.metadata.lastDeath or 0
    local now = os.time()

    -- Example validation: rate-limit repeated death claims to prevent spam.
    if now - lastDeath < 5 then
        -- Reject likely invalid or spammy claims
        TriggerClientEvent('death:client:reject', src, 'rate_limit')
        return
    end

    -- Mark player dead server-side
    Player.PlayerData.metadata.isDead = true
    Player.PlayerData.metadata.lastDeath = now
    Player.Functions.Save() -- persist metadata to DB via QBCore (implementation may vary)

    -- Notify the client to enter downed state and disable controls
    TriggerClientEvent('death:client:enterDowned', src, {bleedout = 120})
    -- Log to server logs for audit
    print(('Player %s marked dead at %s'):format(src, os.date('%c', now)))
end)

This example emphasizes two things: use the implicit server-side source to identify the player, and persist state on the server. The client-provided arguments (clientReportedState) are only hints—never used for authoritative decisions.

Client responsibilities and safety patterns

The client handles animations, control locking, HUD overlays, and showing timers. It should call server events to request transitions, but must be designed under the assumption that a malicious client may call those events excessively or with crafted payloads.

  • Do not set internal client-only variables as the official server state; always wait for the server response.
  • Use client events as "requests" and wait for server-authorized events to change state (e.g., 'death:client:enterDowned').
  • Implement local safeguards to minimize grief: if server ignores repeated requests, show an informative message instead of repeatedly re-sending.

Security and server validation

Protect the system with multiple validation layers:

  • Rate limiting: prevent clients from spamming death requests by storing timestamps.
  • Server side logs: store death events (player, position, weapon hash, timestamp) to identify patterns of abuse.
  • Revocation on suspicious activity: if the same player sends impossible sequences (many deaths per second), mark them for manual review and refuse automated respawn.
  • Authority checks: only allow job roles or players that meet server criteria to revive others. Always verify src and lookup their job via QBCore.Functions.GetPlayer(src).
  • Database sanity checks: when loading player metadata on connect, verify values are within expected ranges and correct malformed entries.

Handling inventory and money

Decide your policy (drop items, retain on death, or temporary inventory freeze). Any changes affecting inventory must be performed server-side using secure functions (Player.Functions.RemoveItem, Player.Functions.AddMoney, or direct DB updates) and logged for audit.

Alternatives and extensions: ESX, ox_lib and common patterns

If you use ESX or ox_lib, the core principles remain the same: server authoritative state, event validation, and persistent metadata. Implementation details differ:

  • ESX: use ESX.GetPlayerFromId(source) and ESX.SaveToDatabase or shared objects to persist state. Many ESX resources use MySQL.Async to save metadata.
  • ox_lib: leverage ox_inventory and ox_core patterns; use exports and server callbacks provided by ox_lib to get consistent player objects and metadata save patterns.

Avoid reinventing persistence when the framework provides safe APIs for player metadata. Use those APIs to ensure compatibility with other resources.

Roblox/Luau considerations (server authority & RemoteEvent handling)

For Roblox developers who want similar behavior, the important rules are: RemoteEvents should be treated as client requests only. All authoritative state must live on the server (in memory, or persisted via DataStores). When you use RemoteEvent.OnServerEvent, the first parameter is the Player instance sent by the engine -- never accept a player id string from the client.

-- Example Roblox server pattern (Luau)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local deathEvent = ReplicatedStorage:WaitForChild("DeathRequest")
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerData")

deathEvent.OnServerEvent:Connect(function(player, clientHint)
    -- 'player' is authoritative. clientHint is a suggestion only.
    -- Verify server-side conditions here.
    local userId = player.UserId
    -- Update in-memory state and use pcall for DataStore ops
    local succ, err = pcall(function()
        playerDataStore:SetAsync(tostring(userId)..":isDead", true)
    end)
    if not succ then
        -- handle DataStore failures: retry/backoff and notify player
        warn("DataStore error saving death state for", player.Name, err)
    end
end)

DataStore failures are common: always wrap in pcall, implement retries or fallback caching, and surface friendly messages to players when persistence is temporarily unavailable.

Testing checklist and table

Validate all interaction flows with a systematic test plan. The table below is a pragmatic checklist to run in staging before production.

Test Steps Expected Result Notes
Basic death flow Cause player to die; client requests death; server validates and marks dead Client receives enterDowned and server metadata shows isDead=true Check DB persistence
Rate-limit abuse Spam death requests from client Server rejects excess requests and logs incident Verify reject message shown to client
Revive by EMS Authorized player triggers revive action Server validates role, revives player, updates metadata and DB Ensure animations triggered on both players
Inventory handling Die with valuable items Server applies configured policy (drop/keep), changes saved Check logs for removed items
Reconnect after death Player disconnects while dead and reconnects Server reads metadata and re-applies correct downed state or respawn Validate session persistence
Network partition Simulate loss between client and server during death flow Server times out or gracefully handles incomplete requests Ensure no inconsistent DB state

Testing, deployment, and maintenance

Before you deploy to production:

  1. Run the tabled tests above in a staging environment that mirrors production as closely as possible.
  2. Enable verbose logging for the first week to capture unexpected flows.
  3. Deploy with feature flags: enable the new death flow for a small population first.
  4. Monitor metrics like death event rate, revive rate, DB errors, and unusual spikes in death claims.

For team workflows, track tasks and assets using project management tools and tie changes to a versioned release. Use the Stellar AI app to manage release notes and SEO assets: Stellar AI project. For technical write-ups and deeper posts about lifecycle and patterns, see our content hub: blog.

Operational best practices

Maintenance and operational hygiene:

  • Rotate any credentials and keep your DB access minimal for the game server account.
  • Keep a changelog and migration script for metadata keys when you modify schema.
  • Run periodic audits of death logs to detect automated abuse or exploitation.
  • Instrument critical code paths with structured logs so you can correlate client events with server-side actions.

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 →