Speed

Not 10–20% faster. Orders of magnitude.

Lattice is a ground-up replacement for the Jellyfin server. It speaks the Jellyfin API your apps already use, but underneath, the library is an event-sourced ledger. Every list you browse, every search and every “what changed?” answer is precomputed when the library changes, not recomputed each time you ask. That one decision is why the gap below is so wide, and why it widens as your library grows.

Every number here was measured on one real household library of about 40,000 items (5,300 movies, 930 series, 31,000 episodes), using Infuse on an Apple TV 4K and an iPhone. How we measured.

Day one

Loading a library: minutes, not days.

How long a brand-new library takes, from files on disk to playable and fully dressed. Same machine, cold start, one server at a time.

Until every file is playable · metadata from NFO files
LibraryJellyfin tunedJellyfin defaultLatticeFaster
1,000 files5.5 min4.7 min15.8 s21×
5,000 files27.5 min23.8 min69.8 s24×
36,130 files3.37 h2.90 h9.4 min21×

“Faster” is against tuned, the fair Jellyfin setup. 36,130 files is the layout of one whole household library.

Why the gap

Jellyfin writes every item through one SQLite database writer, and the usual workaround for big libraries is to make it scan one item at a time. Lattice probes files in parallel and hands the rest to independent workers. How it’s built.

The gap holds as the library grows: about 21× at a thousand files and at thirty-six thousand.

Posters, overviews and artwork from TMDB · Jellyfin 10.11.10 tuned vs Lattice
LibraryUntil…JellyfinLatticeFaster
1,000 filesplayable8.0 min17.8 s27×
every poster8.0 min17.8 s27×
every overview8.0 min25.8 s19×
fully dressed8.7 min49.8 s10×
5,000 filesplayable48.9 min81.8 s36×
every poster48.8 min81.8 s36×
every overview49.0 min2.0 min25×
fully dressed50.7 min3.8 min13×

Fully dressed: backdrops, logos, cast photos and episode stills too. Single Jellyfin runs, to be polite to the TMDB API. A full 36,130-file run with TMDB on is next.

The typical first load: folders only, TMDB on
LibraryJellyfinLatticeWrong matches
1,000 files, dressed9.3 min47.5 s4 → 0
5,000 files, dressed49.2 min3.2 min13 → 0

Jellyfin tuned. Wrong match: a title tied to someone else’s movie or show.

It would rather ask than guess

Matching folder names to titles, Jellyfin tied every title and got 1.5–2.2% wrong. Lattice left 7–8% for you to confirm and made no wrong match in six runs. A wrong poster is easy to spot; wrong watch history isn’t.

March 2026: 5,292 movies, 897 series and 25,222 episodes into Jellyfin.

It took more than 24 hours. Downloading wasn’t the problem: a large server fetched everything in parallel. Jellyfin’s database was. Fed too fast, its single SQLite writer stalled, and a full scan risked corrupting the database or orphaning metadata.

So we built a harness to protect it. It fed Jellyfin a few seasons at a time, waited until every Jellyfin task had been idle three times in a row, ramped batches from 1 to 30 titles, and halved them whenever the write-ahead log bloated, the API slowed or a task stuck.

That harness is why Lattice exists. The lab equivalent, a library laid out like ours, is playable on Lattice in 9.4 minutes.

This is our account of a real migration, timed by us at the time; the harness’s own logs weren’t kept, so it isn’t a benchmark. The tabs beside it are.

Reported by Jellyfin users
Library, as reportedTime, as reportedHardwareSource
~1K movies + ~1K episodes12 h+ first scan, then 40% after 3 more hoursIntel N150, Dockerforum
~2,000 titles (×2 copies)24 h+, still runningmedia on HDDGitHub #2600
~6 TB40% at 2 h, 58% at 4 h, finished overnightSynology DS418playforum
~30 TBdiscovery alone ~2 daysZFSGitHub #2600
65 TB movies / 60 TB seriesmovies ~20 h, series 42 h+cloud storageforum (DS923+ thread)

Community reports, not our measurements; hardware and settings vary.

Every day after

Then every tap is instant.

The headline numbers

What you doJellyfin 10.11LatticeDifference
Search as you type (each keystroke, “Blade Runner”)3,000–10,000 msunder 7 ms~500–1,500×
Open an item’s details361 ms1.2–2.7 ms~130–300×
Next Up / Continue Watching184–473 ms1–13 ms~35–180×
“Latest” row~1,000 ms~6 ms~170×
Full library sync (Infuse library mode)3 min 20 s – 3 min 47 s~5 s warm, ~20 s cold~10–48×
Sync when nothing changedfull re-crawl, ~3.5 mina few ms—
Artwork for a phone’s full libraryoriginals, ~530 KB avg~74% smaller~¼ the bytes

In Infuse’s direct mode, every keystroke is a server search. On Jellyfin, each one scans the whole item table for the text you typed. Several are in flight at once, and they queue:

KeystrokeJellyfinLattice
Bla3,295 msunder 7 ms
Blade9,464 msunder 7 ms
Blade R … Blade Runne10,107–10,204 ms eachunder 7 ms
Blade Runner 20493,206 msunder 7 ms

How: when a title is added, Lattice indexes every way you might start typing it (b, bl, bla, … blade r, …) into pre-sorted lists, and decides the ranking (exact title first, movies before episodes and so on) at the same time. A keystroke becomes one keyed read of about 24 entries. That costs the same for a 400-title library as for a 400,000-title one.

2. A full library sync in seconds, not minutes

Infuse’s library mode crawls your entire library, 200 items per page:

JellyfinLattice
Full crawl, ~40,000 items181–193 s server time; 3 min 20 s – 3 min 47 s wall clock4.0–4.8 s warm, ~19–22 s cold
Per page (200 items), p50264–969 ms, grows with library size~15 ms, flat
Season pages, p995.9–7.9 s16–68 ms

And when you tap sync with nothing changed:

3. It stays fast as your library grows

We ran both servers on the same machine, against the same libraries, at four sizes (the full Infuse crawl, warm):

Library sizeJellyfin crawlLattice crawlJellyfin page p50Lattice page p50
1000.34 s0.02 s47 ms1.9 ms
1,0001.9 s0.10 s132 ms14 ms
10,00020 s1.0 s300 ms15 ms
40,000193 s4.0 s969 ms15 ms

Jellyfin’s crawl grows faster than the library: from 10,000 to 40,000 items, four times the items took 9.4 times as long, because each page costs more the further into the library it is (offset paging on SQLite). Lattice pages from a precomputed position, so every page costs the same and the crawl grows exactly with the library.

4. Artwork sized for the screen it’s going to

Infuse’s library mode fetches a poster and backdrop for every title. Jellyfin sends the full originals, averaging about 530 KB each:

Lattice pre-builds renditions for each class of device. The TV tier is backdrops up to 2160 px and posters up to 1000 px; the handheld tier is 1170 px and 600 px. It picks the right one per request: Apple TV gets TV, iPhone and iPad get handheld, browsers get originals. Measured across the real library, 55,457 images per tier:

TierImages rebuiltBytes saved on thoseNotes
TV (Apple TV)25,31550%the other 29,823 were already small and stay original
Handheld (iPhone, iPad)43,82774%about ¼ the bytes; the grid keeps up with your thumb

On a real iPhone’s full artwork sync, Infuse fetched 45,731 images (9.17 GB) from Jellyfin in about 17 minutes and stored 5.73 GB. For those exact images, Lattice’s handheld renditions total 3.49 GB (38%), and the TV tier 5.23 GB (57%). Less transferred means less stored on the phone, too: a library-mode Infuse install grew from 253 MB (direct mode) to 995 MB, then to more than 1.57 GB as artwork filled in, all of it originals.

5. What doesn’t change

How we measured, and what’s still to come

Initial library load

How long a brand-new library takes until every file is playable, measured on a separate benchmark machine with an SSD:

Want to try it on your library? We’re choosing beta testers from the waitlist.

Join the waitlist