A friend of mine bought a 200-car pack on a Friday, uploaded the whole thing on Saturday, and spent Sunday answering Discord messages that all boiled down to "is the server down?" The server was fine. Joining it had simply gone from 41 seconds to a shade under four minutes, and four minutes is a long time to stare at a loading screen for a city you haven't fallen in love with yet.
Most fivem vehicle optimization advice starts and ends at frame rate. The thing that actually mugged him was download weight: the total size of every streamed file a client has to pull before it sees a spawn point. So this post is about where that weight lives, why it's textures far more often than models, how to measure it honestly rather than by vibes, and which cars you can cut without opening a single piece of 3D software.
Why every add-on car downloads even if nobody drives it
The engine has no idea your garage table exists. Everything inside a resource's stream folder gets shipped to the connecting client, in full, before they spawn. There is no lazy loading based on ownership and no prioritisation of the cars that actually get used.
So a 200-car pack is 200 cars' worth of .yft models and .ytd texture dictionaries on the wire. The 170 that have never been spawned cost exactly as much bandwidth as the 30 driven every night.
The saving grace is that FiveM caches per file, keyed by content, so it's a first-visit cost rather than an every-visit one. Two problems with relying on that. First impressions are the only impression a lot of first-time joiners will give you, and when you update a pack those files change and re-download for everyone who already had them. Push a "small livery fix" across 200 vehicles and you've quietly handed your entire playerbase another four-minute join.
What actually makes a vehicle heavy: textures, not the model
Open any bloated add-on car and the model file is rarely the villain. The .ytd is.
The arithmetic is easy and depressing. A 4096x4096 texture stored as DXT5 is 16 MB of pixel data, and mipmaps push it to roughly 21 MB. The same texture at 2048x2048 is 4 MB, or about 5.3 MB with mips. One resolution step down on one livery saves you more bytes than most people's entire handling folder. Now count how many 4K files a pack of 200 cars is carrying.
Worse, plenty of packs ship textures with no block compression at all. An uncompressed 32-bit 2048x2048 image is 16 MB where the DXT5 version is 4 MB, and it looks the same at any distance a player will ever view a car door from.
Four sins turn up again and again:
- 4K liveries on cars nobody inspects closely, usually a background sedan whose entire job is existing in traffic.
- Uncompressed or badly compressed DDS files, often because the author exported once and never looked at the options.
- Duplicated texture dictionaries across colour variants, where the same car ships six times as six "models", each carrying a full copy of the body, glass, interior and wheel textures so that one paint file can be different.
- Generic assets embedded in every model instead of shared, so 200 cars each carry their own copy of interior plastics, dial faces, tyre treads and glass. Vanilla GTA V puts those in a shared dictionary for exactly this reason, and converted models routinely ignore that and pack their own.
If you want to get properly hands-on with the DDS side of this, the walkthrough on FiveM texture optimization covers compression formats and mipmap settings in more depth than I can fit here.
How many polygons is too many for a FiveM car?
Model weight bills you at a different counter. Textures hurt your join time and your VRAM; geometry hurts your frame rate and your streaming pool.
Vanilla GTA V vehicles sit roughly in the low hundreds of thousands of triangles across all their detail levels, built for a game that expects a dozen of them on screen alongside peds, buildings and traffic. Conversions from racing sims are commonly several times that, because they came from a game that renders one car on a clean track with nothing else competing for memory. They look incredible in a screenshot and behave badly in a busy city centre.
The related sin is lazy LODs. A properly built car has progressively cheaper versions of itself for distance rendering, plus the _hi.yft that streams in on top for close-up detail. Packs that copy the highest detail level into every LOD slot leave the engine with no cheap option, so a car park of twenty is priced like twenty hero models at all times.
When the streaming pool fills up, the symptoms are recognisable: vehicles spawning invisible or missing wheels, textures stuck at potato resolution long after they should have resolved, props with no collision. Those are not "FiveM being FiveM". Those are your asset budget telling you it's out.
"It runs fine for me" means nothing
Every owner says this, and every owner is wrong for the same reason: you have the cache. You downloaded those files when you tested the pack. Your client has never once done what a new player's client has to do.
You are also, usually, sitting on a fast connection with a warm DNS entry and possibly the server itself in the next room. The person deciding whether your city is worth a second look is on hotel wifi with a laptop that thinks 60fps is aspirational.
Until you've timed a join from a genuinely clean cache on an ordinary connection, you don't have a number. You have a feeling, and feelings are terrible at measuring megabytes.
How to measure your server's streamed asset size
Start on the server. This gives you every stream folder ranked by weight:
find resources -type d -name stream -exec du -sh {} + | sort -h
Then find the individual offenders, because one resource is usually carrying the whole problem:
find resources -path '*/stream/*' -name '*.ytd' -printf '%s\t%p\n' | sort -rn | head -40
That second command takes about a second and hands you the forty fattest texture dictionaries on your entire server. In my experience the top ten are enough to explain most of the join time. As a rough sanity check, a well-built add-on car often lands somewhere in the 10 to 25 MB range for everything it ships. Anything past 100 MB is almost never a modelling decision, it's a texture that was never resized.
Then do the client-side test properly. Close FiveM completely, including any leftover CitizenFX processes, then go to %localappdata%\FiveM\FiveM.app\data and rename (don't delete, rename) the cache, server-cache and server-cache-priv folders. Join your server with a stopwatch running from connect to spawn. Write the number down. That number is your actual first-impression cost, and it's the only one worth arguing about.
Do it again after every round of cuts. Fixing this without measuring is just rearranging files with extra steps.
Which vehicles should you cut from a bloated pack?
Here's the part nobody wants to hear: a fleet of 30 well-chosen cars beats 200 filler ones, and your own database already knows which 170 to bin.
On QBCore, the owned vehicles live in player_vehicles with the spawn name in the vehicle column, so the whole audit is one query:
SELECT vehicle, COUNT(*) AS owned
FROM player_vehicles
GROUP BY vehicle
ORDER BY owned DESC;
ESX keeps the model inside a JSON blob on owned_vehicles, usually as a hash rather than a name, so you'll need to map hashes back to spawn names before the list means anything. Either way, cross-reference the result against your dealership stock and your job vehicle configs so you don't delete something a script spawns.
Then be honest about the tail. A car with zero owners after three months of live play isn't undiscovered, it's furniture. It's furniture that every single new player pays to download.
Curation also just reads better. A coherent, deliberate fleet, say a properly built JDM import scene with cars that belong to the same story, feels richer to a player than 200 unrelated vehicles where half the spawn names are police_v3_final_FIXED. Quantity is the easiest thing to advertise and the least interesting thing to own.
When you're restocking, check the pack's total unpacked size before you check the car count. Most of the questions worth asking before you buy are covered in this vehicle pack buying guide, and file weight belongs on that list right next to the licensing.
Fixes that don't need a modeller
You can do all of these with OpenIV or CodeWalker and an afternoon:
- Downscale oversized textures. Export the DDS files from the heavy
.ytds, look at the dimensions, and drop anything 4096 that isn't a livery you can read from the driver's seat to 2048. Re-import as DXT5, or DXT1 where there's no alpha channel, with mipmaps kept. - Collapse colour variants. If a pack shipped six near-identical models that differ only in paint, keep one and handle the colours through
carvariations.metaor livery slots instead of six full texture dictionaries. - Move the long tail into a separate resource you only start for events. This works well, with one caveat worth knowing: starting a stream resource mid-session makes connected clients download it right then, so start it a few minutes before the event rather than on the countdown.
- Check what your manifest is actually shipping. A lazy
files {'**/*'}glob will cheerfully send players the pack's preview renders, readme and leftover PSD source files. I've seen a resource where the promotional screenshots outweighed the cars.
Do replace vehicles load faster than add-ons?
This one comes up every time someone's join time gets embarrassing, and the answer is no.
A replace vehicle still ships you a .yft and a .ytd, and the client still downloads both. On bandwidth, an add-on and a replace of the same car cost the same. What a replace actually saves is registry pressure: no new entry in vehicles.meta, no additional model in the game's vehicle list, so you stay further from the ceiling on unique models and keep your meta files manageable.
What it costs you is the vanilla car, permanently, along with every script, job, dealership and traffic population setting that referenced it. So converting your add-ons to replaces is a model-count decision. If your problem is a four-minute join, it buys you nothing at all.
Where compression and CDNs genuinely help
Block compression inside the .ytd is the single biggest lever, and it works twice: smaller on the wire, and smaller in VRAM, since the GPU keeps DXT data compressed rather than expanding it. Mipmaps add roughly a third to the file size and are still worth keeping, because without them the engine renders full-resolution textures at distance and thrashes the streaming pool doing it.
FiveM can also point clients at a CDN for the download instead of pushing everything through your game server's uplink. That doesn't reduce a single byte, but it changes wall-clock time considerably and stops thirty people joining at once from saturating the box while it's also trying to run your city. Most decent hosts will hand you the convar.
And a small ask for your Discord: stop telling players to clear their cache as step one of every support reply. That advice fixes about one problem in ten and guarantees they'll be re-downloading your entire fleet next time they join.
The weekend audit
Six steps, and you can genuinely finish them between Saturday morning and Sunday lunch:
- Sum your stream folders and find the top forty
.ytdfiles by size. - Run the clean-cache join test and write the number on something you won't lose.
- Run the owner-count query and list every spawn name with zero owners.
- Downscale the worst textures and collapse any duplicate colour variants.
- Move the survivors nobody drives into an event-only resource, and delete what's left.
- Run the join test again and compare.
My friend kept 58 of his 200 cars. Join times came back into the range where people wait rather than alt-tab, and here's the bit that surprised him: in three weeks, not one person asked where the other 142 went. Turns out nobody was driving the furniture.



