Why Unsynced Weather Breaks Your City
Out of the box, GTA V treats weather like a personal opinion. Every client runs its own local simulation, so without FiveM weather sync your cop is chasing a suspect through a thunderstorm while the suspect enjoys a lovely sunset two cars ahead. Same street, two different skies, and the rain-slick handling penalty only applies to one of them. That last part is the killer. Weather isn't cosmetic in GTA V because rain changes grip, night changes visibility, and fog changes how far a sniper on a roof can actually see. If those conditions differ per player, you're not running one city. You're running thirty two slightly different cities that happen to share a map.
Time is worse. The default GTA clock ticks one in-game minute every two real seconds, and each client ticks it independently from whenever they loaded in. Player A joins at server-noon, player B joins ten minutes later, and now their clocks drift apart forever. Scene lighting stops matching between players, screenshots from the same event look like different days, and your "midnight heist" starts at 3 PM for half the crew.
The fix is one rule: the server owns the sky. One authoritative weather state and one authoritative clock, pushed to every client. Everything else in this post is just ways to implement that rule.
The Natives Behind FiveM Weather Sync
FiveM weather sync works by having the server hold a single weather type and clock time, then having every client force-apply that state with natives instead of running GTA's local simulation. The server broadcasts on change and on player join, and clients override their local weather and clock to match.
On the client, the heavy lifting comes down to a handful of natives:
-- Transition smoothly to the server's weather over 15 seconds
SetWeatherTypeOvertimePersist('THUNDER', 15.0)
-- Or snap instantly (joins, admin commands)
SetWeatherTypeNowPersist('THUNDER')
-- The clock is needier: this must run every frame,
-- or GTA quietly reverts to its own time calculation
CreateThread(function()
while true do
NetworkOverrideClockTime(serverHour, serverMinute, serverSecond)
Wait(0)
end
end)
That NetworkOverrideClockTime loop is the classic gotcha. Call it once and the clock obeys for a moment, then drifts right back, and you'll spend an evening convinced the native is broken. It isn't. It just has the memory of a goldfish. The Persist variants of the weather natives are better behaved and hold until you call ClearWeatherTypePersist().
For moving the state around, older resources broadcast TriggerClientEvent to everyone on a timer. Modern ones lean on state bags instead: the server sets GlobalState.weather once, and every client picks up the change through a state bag handler. New joiners read the current value immediately with no "send me the weather" handshake, and nothing gets rebroadcast to players who already have it. If you're writing your own sync in 2026, state bags are the correct answer.
Picking a Weather Sync Script
You almost certainly shouldn't write your own, because this problem has been solved several times over:
- qb-weathersync ships with QBCore and is the default for a reason. Server-side rotation, shared clock, blackout mode, and admin commands like
/weather,/freezetime,/freezeweatherand/blackout. The sync logic is plain Lua, so it runs fine outside QBCore too. - Renewed-Weathersync is the drop-in upgrade. It pre-renders the entire weather queue server-side, syncs through state bags, and is noticeably lighter than qb-weathersync on both server and client. It ships compatibility layers for qb-weathersync and cd_easytime exports, so most dependent scripts keep working untouched.
- cd_easytime is the admin-friendly pick: a clean UI for changing time and weather with a click, dynamic weather, and optional real-world weather pulled from OpenWeatherMap. Yes, you can make virtual Los Santos match the actual rain outside your window. Whether your players want to import British weather is between you and them.
- vSync and kibook/weathersync are the lightweight standalones. Older, simpler, still fine for a minimal server, and kibook's also runs on RedM.
Whichever you pick, run exactly one. Two sync resources will fight over the sky like siblings over a thermostat, and the visible symptom is weather that flickers between states every few seconds. The usual culprit is vMenu, which has its own sync enabled by default. Disable it in server.cfg with setr vmenu_enable_weather_sync false and setr vmenu_enable_time_sync false before blaming your weathersync resource. Full storefronts like scripts-tebex.io carry plenty of weather and environment tooling if you want something with more production polish than the free options.
Building a Blackout or Storm Event
A blackout is one native and a lot of consequences:
-- Server
GlobalState.blackout = true
-- Client, in a state bag handler
SetArtificialLightsState(true)
SetArtificialLightsStateAffectsVehicles(false) -- headlights stay on
SetArtificialLightsState(true) kills every artificial light on the map: streetlights, building windows, the works. Leaving vehicle lights functional via the second native matters more than it sounds, because a city where headlights don't work isn't spooky, it's a demolition derby.
The trick that separates a blackout event from a blackout toggle is wiring other scripts to the same state. Because it's in GlobalState, any resource can check it: take ATMs offline, disable store alarms, widen the loot table on house robberies while the power's out. Now the blackout is a gameplay window instead of a lighting change, and your criminal players will start praying for storms. [switches to serious face] Announce it in-character first, through a weazel news post or a power company alert, because sixty seconds of warning turns "the server broke" into "something is happening."
For the storm itself, stack the layers: SetWeatherTypeOvertimePersist('THUNDER', 30.0) for the rolling transition, freeze the rotation so your event doesn't clear up mid-heist, kill the lights, then walk it all back afterwards with a slow transition to CLEARING. That after-the-rain state is a nice touch players notice without knowing why.
Seasonal Events: Snow, Halloween and the Calendar
GTA V ships weather types that most sync scripts deliberately exclude from rotation: SNOW, BLIZZARD, SNOWLIGHT, XMAS and HALLOWEEN. They're excluded because random snow in July breaks immersion, but they're gold when you schedule them on purpose.
XMAS is the big one. It covers the whole map in snow, and two extra natives sell the effect:
SetWeatherTypeNowPersist('XMAS')
ForceSnowPass(true) -- force the snow render pass
SetForcePedFootstepsTracks(true) -- footprints in the snow
SetForceVehicleTrails(true) -- tyre trails
Those trails are the detail players screenshot. Snowballs usually need a small extra script that hands out WEAPON_SNOWBALL when someone scoops, and it's worth the ten minutes, because nothing defuses cop-versus-criminal tension like a departmental snowball fight.
Scheduling is plain server-side Lua. Check os.date('*t') on resource start, and if the month is December, override the rotation:
local now = os.date('*t')
if now.month == 12 then
GlobalState.weather = 'XMAS'
GlobalState.weatherFrozen = true
end
HALLOWEEN plus fog plus a scheduled blackout makes October week basically run itself. If you're going all-in, seasonal MLOs and props from a catalog like assets-tebex.io dress the set, and the weather does the mood lighting for free.
Time Control and the Performance Bill
Most sync scripts let you set milliseconds per game minute, and this is quietly one of the biggest RP levers you have. Crime RP peaks at night, police shifts cluster in the evening, so many servers stretch night hours and compress the dead afternoon. Renewed-Weathersync supports dynamic scaling out of the box for exactly this. Freezing time entirely has its place too, for photo shoots, court scenes, or any event where lighting continuity matters.
Performance-wise, weather sync done right is nearly free. One server loop owns the state, changes go out via state bags, and the only per-frame client cost is that mandatory clock override. If your sync resource shows meaningful resmon numbers, it's rebroadcasting on a timer instead of on change, and you should swap it for one that doesn't. The optimization-focused resources at 0resmon-tebex.io exist because this niche cares about exactly this kind of waste, and the sky is a silly thing to spend frame time on.
The Forecast, in Short
Server owns the sky, clients obey, and you run exactly one resource enforcing it. Pick qb-weathersync for the QBCore default, Renewed-Weathersync for the lighter upgrade, cd_easytime if your admins like buttons. Then use the control you've gained: blackouts wired into gameplay, a thunderstorm that arrives on schedule, snow with real footprints in December. Your city stops having thirty two private skies and starts having weather that means something. Forecast for your server: cloudy, with a high chance of immersion.