# Keeping FiveM NUI fast

> Make FiveM NUI cheap to run: sending messages only on change, throttling HUD updates, hiding closed UIs with display:none, animating transform and opacity only, avoiding heavy shadows and filters, React re-render tips, image sizes, and measuring cost in resmon and devtools.

Source: https://fam-tools.com/guides/fivem-nui-performance · FAM Tools · published 2026-09-11 · updated 2026-09-11 · about 10 min

**Short answer.** Send NUI messages only when values change, and throttle continuous data (speed, fuel) to a few updates per second. Hide closed UIs with `display: none`, animate only `transform` and `opacity`, avoid large blurs and shadows, keep images the size they are displayed at, and stop React from re-rendering the whole tree on every message. Measure the Lua side in resmon and the page in the devtools Performance tab.

## Key points

- Never `SendNUIMessage` every frame — send on change, throttle to ~4–10/s.
- Closed UI = `display: none`.
- Animate `transform`/`opacity`; avoid animating layout.
- No `backdrop-filter`, few big shadows.
- Measure: resmon for Lua, devtools for rendering.

A HUD that costs 2 FPS is a HUD every player pays for, all session long. NUI cost has two halves: the Lua side sending data (visible in resmon) and the browser side rendering it (visible as lower FPS and in the devtools). Both are easy to keep small once you know the patterns.

## Send less, less often

*client.lua — speedometer updates only on change*

```lua
local last = {}

CreateThread(function()
    while true do
        local sleep = 500
        local veh = GetVehiclePedIsIn(PlayerPedId(), false)
        if veh ~= 0 then
            sleep = 150
            local speed = math.floor(GetEntitySpeed(veh) * 3.6)
            local fuel = math.floor(GetVehicleFuelLevel(veh))
            if speed ~= last.speed or fuel ~= last.fuel then
                last.speed, last.fuel = speed, fuel
                SendNUIMessage({ action = 'vehicle', speed = speed, fuel = fuel })
            end
        elseif last.speed then
            last = {}
            SendNUIMessage({ action = 'vehicle', hide = true })
        end
        Wait(sleep)
    end
end)
```

Each message is encoded to JSON and handed to the browser process. Rounding values and sending only changes turns hundreds of messages per second into a handful.

## Cheap CSS

| Expensive | Cheaper |
| --- | --- |
| Animating `width`, `top`, `left` | `transform: translate/scale` |
| `backdrop-filter`, big `filter: blur()` | Semi-transparent solid backgrounds |
| Many large, soft `box-shadow`s | One small shadow or a border |
| Hidden with `opacity: 0` | `display: none` when closed |
| Huge PNGs scaled down in CSS | Images exported at display size, WebP |

## React and framework UIs

- Store fast-changing values (speed, health) in small components, not in a top-level state that re-renders everything.
- Use `React.memo` / selectors so a speed update does not re-render the inventory grid.
- Unmount closed screens instead of rendering them invisibly.
- Build for production — development builds are much slower.

## Measuring

Resmon shows the Lua cost of your client thread (aim for 0.00–0.02 ms idle). Rendering cost does not appear there: record a few seconds in the devtools Performance tab and compare in-game FPS with the UI open and closed. See [NUI devtools](https://fam-tools.com/guides/fivem-nui-devtools-debugging) and [resmon explained](https://pityus.net/guides/fivem-resmon-resource-time).

## Loading screens

Loading screens compete with the game loading itself. The same rules apply, plus file size — see [loading screen performance](https://fam-tools.com/guides/fivem-loading-screen-performance).

## Questions

### Why does my HUD lower FPS?

Usually messages sent every frame, heavy CSS effects, or a framework re-rendering everything on each update.

### How often should a HUD update?

Only when values change, and at most around 4–10 times per second for continuous values like speed.

### Does resmon show NUI rendering cost?

No. Resmon shows the Lua side; use in-game FPS and the devtools Performance tab for rendering.

### Should I hide UI with opacity or display none?

`display: none` for closed UIs — invisible elements still cost rendering.

## Related

- https://fam-tools.com/guides/fivem-nui-cef-limitations
- https://fam-tools.com/guides/fivem-hud-design-principles
- https://fam-tools.com/guides/fivem-nui-devtools-debugging
- https://fam-tools.com/guides/fivem-loading-screen-performance
