AI & INFRASTRUCTURE

More than you ever wanted to know about Engrams in DeepSeek 4.1

A deep dive into DeepSeek V4.1 Flash’s Engram memory: lookup mechanics, token deadlines, latency tables, SSD experiments and remote RAM over Thunderbolt and Ethernet.

  • Andreas Petersson
  • 20 min read
188.8 GiB stored in two Engram tables, but only 12.4 KiB read per text token: 48 rows of 264 bytes.
A huge footprint, a tiny read per token, and two very different deadlines.

DeepSeek V4.1 Flash ships with 188.8 GiB of n-gram lookup tables. That’s before expert weights, attention caches or anything else the inference engine needs. So does all of it have to sit in RAM—or can an SSD, or even another machine, serve it fast enough?

Each token reads just 48 of those rows: 12.4 KiB. The catch is timing. The first 24 rows are needed after a single layer of compute—about 0.6 ms at 40 tokens/s—and they’re scattered across a 94 GiB file. I worked through the timing and measured the storage I had at hand: an internal and an external SSD on an M5 Ultra, and a second machine’s RAM over Thunderbolt and gigabit Ethernet.

Short answer: give Table 0 the fastest path you have. It’s needed at block 1, while Table 1 can wait until block 14. A decent NVMe drive keeps up to roughly 40–60 tokens/s, and a late read costs a few percent rather than a collapse. Remote RAM over Thunderbolt is faster still, as long as the engine batches the rows into one request. On macOS, DwarfStar currently reads both tables before computing anything, so the read time adds to every token. And don’t quantise the tables harder to save disk: on an SSD a smaller row reads no faster, so the quality you give up buys nothing.

What’s measured and what’s modelled

  • Measured: per-row SSD latencies (Python harness, macOS, M5 Ultra, 25 October 2026) and remote-RAM batch round trips (a small C daemon over TCP). I did not run DwarfStar end to end.
  • Derived: SSD table-fetch times, calculated as six times the per-row median.
  • Modelled: every deadline and the heatmap. They describe DwarfStar’s asynchronous reader at the commit linked at the end, where four reader threads overlap the reads with computation, for a single decode stream. Above 100 tokens/s they are sensitivity analysis.
Terms used in this article
Token
The unit a language model reads and writes: a word, part of a word or a punctuation mark, stored as an integer ID.
n-gram
A run of n consecutive tokens. Here: the last two, three or four tokens up to the current one.
Engram
DeepSeek’s name for a learned n-gram memory. Hashes of recent n-grams pick rows from large tables, and the model mixes those rows into its working state. Trained with the model, not filled at run time.
Block (layer)
One step of the model’s stack: attention plus a feed-forward network. V4.1 Flash has 40, numbered 0–39.
Working state / residual
The vectors that carry each token through the stack. Every block reads them and adds its result back. V4.1 keeps four parallel streams of this state.
Hash head
One of eight independent hash functions per n-gram length. Each produces one row address, so collisions in one head are evened out by the others.
Row read / table fetch / network batch
A row read returns one 264-byte row. A table fetch is the 24 rows one block needs. A network batch is one message carrying several row requests. Their latencies can’t be compared directly.
Mixture of experts (MoE)
A feed-forward network split into many “experts”, of which only a few run for each token. The expert weights are large, which is why they are sometimes streamed from disk.
Decode / prefill
Decode generates one token per step and is what this article times. Prefill processes the whole prompt in one go.
Speculative decoding
A small draft model guesses several tokens ahead; the large model checks them in one verification pass.
p50, p99, p99.9
Percentiles: half of all reads were faster than p50, 99% faster than p99, 99.9% faster than p99.9.
IOPS
Input/output operations per second: how many separate reads a drive completes.
RDMA
Remote direct memory access: a network reads another machine’s RAM without involving its CPU. Not used in these tests.
Quantisation
Storing values with fewer bits. These tables use 8-bit values with one shared scale per 32 values; a 4-bit version would halve the size but round every value more coarsely.
KiB / GiB vs KB / GB
Binary units (1 KiB = 1,024 bytes) versus decimal ones (1 KB = 1,000 bytes). 12.4 KiB is 12,672 bytes.

1. Where Engram sits in the model

V4.1 Flash is a stack of 40 blocks—model layers, nothing to do with SSD blocks. In each one, attention pulls in context from earlier tokens and a mixture of experts transforms the result; both are added back to the working state. Engram adds a third contribution, but only in two blocks, just before attention.

Engram enters the 40-block stack twiceEach square is one block, numbered 0 to 39.
Inside a block
  1. Receive the working state from the previous block.
  2. Blocks 1 and 14 only: add the gated Engram value.
  3. Mix the four streams, normalise, run attention.
  4. Add the attention result back.
  5. Mix and normalise again, run the mixture of experts.
  6. Add that result back and hand the state on.
Inside one Engram lookup
  1. 4 tokenscurrent + 3 before, compressed IDs
  2. 3 suffixes × 8 hash headslast 2, 3 and 4 tokens
  3. 24 rows × 264 Bfetched from RAM, SSD or network
  4. 6,144 values8-bit, one scale per 32
  5. 4 keys + 1 value5,120 wide each
  6. gate × valueadded to each of the 4 streams

The lookup works on token IDs, not text. The engine maps the current token and the three before it into a compressed vocabulary, so some spelling variants share an ID. It hashes the last two, three and four tokens with eight hash heads each: 24 row addresses per table, 48 per token. Each row holds 256 eight-bit values and eight one-byte scales, 264 bytes in all.

Engram in DwarfStar’s V4.1 Flash implementation. The per-token read follows from row count and row size.
ItemValue
Blocks in the model40, numbered 0–39
Blocks that use the tables1 (Table 0) and 14 (Table 1)
n-gram sizes hashed2, 3 and 4 tokens
Rows per token per table24 (3 sizes × 8 hash heads)
Row size264 B (256 values + 8 one-byte scales)
Read per text token48 × 264 = 12,672 B ≈ 12.4 KiB
Tables on disk188.8 GiB total
Lookback kept per inference requestLast 3 compressed token IDs

The rows become four keys—one per working stream—and one shared value. Each stream compares its state with its key, and the score becomes a gate between zero and one. It’s learned memory inside the forward pass, closer to an embedding table than to retrieval-augmented generation; nothing is inserted into the prompt. Image-placeholder positions are masked, and the speculative decoder’s draft model doesn’t use Engram at all.

2. One token, from lookup keys to output

The row addresses depend only on token IDs, so the CPU can compute them and start reading before the GPU reaches block 1. With the asynchronous reader, block 0 hides the Table 0 reads, and blocks 1 to 13 hide Table 1. macOS works differently—open the last drill-down or see chapter 3.

One token with overlapping readsSchematic, not to scale: blocks 15–39 are drawn narrower.
GPU
Table 0
needed
Table 1
neededno Engram reads
Table 0
1 block
Table 1
13 blocks
Blocks 15–39
no Engram I/O
The four reader chains

Each worker reads six Table 0 rows (dark), then six Table 1 rows (light). There is no barrier between the tables, so worker 3’s slow read delays Table 0 while the others already work on Table 1. Illustrative timings.

Worker 1
Worker 2
Worker 3
Worker 4
Table 0 complete
Step by step
  1. The CPU hashes the token and its lookback; four reader threads start on Table 0. The token is embedded.
  2. Block 0 runs attention and experts while the reads continue.
  3. Block 1 waits for Table 0 if needed, projects, gates and adds, then runs as usual.
  4. Blocks 2–13 run while the same readers fetch Table 1.
  5. Block 14 consumes Table 1 the same way: the second and last injection.
  6. Blocks 15–39, the output layer and sampling pick the next token. The consumed token joins the three-token history.
The macOS path at this commit

No overlap reader: both tables are read with 16 workers before the token is embedded, and the GPU waits for all of it.

Reads
GPU
waits

3. The timing model

The asynchronous token path uses TOKEN_READERS = 4. Each worker reads six rows per table in sequence, so the per-row budget is the table’s window divided by six. At 40 tokens/s Table 0 has about 625 µs, roughly 104 µs per row. Under four-reader load the median row read took 68 µs on the internal SSD and 99 µs on the external one—both inside the budget. At 100 tokens/s the budget drops to 42 µs and both miss.

Asynchronous overlap model: block time ≈ W/40, four readers × six rows per table, so row budget = window ÷ 6. Payload is logical, in decimal MB.
BaselineToken timemsTable 0 windowms · 1 blockTable 1 windowms · 13 blocksTable 0 row budgetµsTable 1 row budgetµsPayloadreads/s · MB/s
15 t/s66.671.66721.672783,6117200.19
20 t/s50.001.25016.252082,7089600.25
30 t/s33.330.83310.831391,8061,4400.38
40 t/s25.000.6258.131041,3541,9200.51
60 t/s16.670.4175.4269.49032,8800.76
70 t/s14.290.3574.6459.57743,3600.89
100 t/s10.000.2503.2541.75424,8001.27
Above 100 t/s: single-stream sensitivity analysis
300 t/s3.330.0831.0813.918114,4003.80
600 t/s1.670.0420.546.990.328,8007.60

With those medians, the internal drive keeps up to about 61 tokens/s and the external one to about 42. That’s arithmetic on a median; the tail is in chapter 4.

A late table costs its overshoot

Missing a window isn’t a cliff. A late fetch adds only the time by which it overshoots; the blocks already computed stay computed.

The first 1.25 ms of a token at 100 tokens/sTo scale. One block takes 0.25 ms; Table 0 is needed when block 1 starts.

Thunderbolt batch · 0.095 ms fetchno stall

Table 0
GPU
01234

External SSD, 4 × 6 reads · 0.59 ms fetch+0.34 ms stall

Table 0
GPU
0wait123

At 100 tokens/s that overshoot is 0.34 ms on a 10 ms token: 3.4% more time, about 96.7 tokens/s. The same 100 µs overshoot costs 0.4% of a 25 ms token and 6% of a 1.67 ms one—the faster the GPU, the less time storage has to hide. At a hypothetical 600 tokens/s even Table 1 misses with 0.59 ms fetches (442 tokens/s), and a 2.4 ms fetch, roughly one reader working through all 24 rows, leaves about 170.

The formula and its limits
w₀ = W / 40
w₁ = 13W / 40

extra = max(0, f₀ − w₀)
      + max(0, f₁ − w₁)

T = W + extra  (ms)
slowdown = extra / W
tokens/s = 1000 / T

W is the token time without Engram stalls, f₀ and f₁ the two fetch times, and every block counts as W/40. The formula is exact when Table 0 misses, because block 14 moves back by the same stall, and slightly pessimistic when Table 0 arrives early. Real workers overlap the two tables, early Table 1 reads can queue behind Table 0, and embedding, sampling, the output head and CPU–GPU synchronisation take part of W. Treat it as a planning tool until you have a trace.

264 bytes in, kilobytes off the flash

The logical payload is tiny: 1.27 MB/s at 100 tokens/s. The drive moves more. If every row read pulls a 4 KiB page, 600 tokens/s means 28,800 reads/s and about 118 MB/s; with 16 KiB pages it’s about 472 MB/s. Either way, for one stream random-read latency matters and an SSD’s sequential GB/s rating says little.

macOS works differently at this commit. Non-Apple builds create the asynchronous reader and overlap its four workers with computation, unless DS4_DISABLE_V41_ENGRAM_OVERLAP is set. On macOS the reader is never created, so the token step reads Table 0 and then Table 1 through ds4_engram_read_batch before embedding and block 0. That batch reader uses 16 workers from eight rows up on Apple platforms (from 256 rows elsewhere, so large prefill batches use 16 too).

Nothing hides those reads: if F is the time for both batches, a token takes T = W + F. The windows, the heatmap and the four-reader SSD estimates don’t apply, so F has to be measured on its own.

4. Inside the SSD experiments

I ran the disk tests on an Apple M5 Ultra with 256 GiB RAM under macOS, using Python’s os.pread with F_NOCACHE to keep the file cache out. The internal SSD read a 2 GiB zero-filled scratch file; the external Samsung 4 TB volume read an actual 94.4 GiB Engram table. One reader, then four, 264 bytes per read, about four seconds each. The harness times single reads, never a whole 24-row lookup—hence the derived 6 × 68 µs = 0.41 ms and 6 × 98.6 µs = 0.59 ms per table.

Per-row read latency: median versus tailLog scale. Each row is one harness configuration.
  • p50
  • p99
  • p99.9
  • max
Internal · 1 reader
Internal · 4 readers
External · 1 reader
External · 4 readers
  • ATable 0 row budget at 40 t/s (104 µs)
  • BTable 0 row budget at 100 t/s (42 µs)

One read in a thousand takes 2 ms

On the external drive with four readers, the median row read was 98.6 µs, but the p99.9 was 2.05 ms and the slowest read took 36.8 ms. One read like that stalls its whole chain, and the fetch waits for the slowest of the four chains. Using the 121.4 µs mean instead of the median gives 0.73 ms per table and 4.8% extra token time at 100 tokens/s—and even that is a floor, because the slowest of four chains takes at least six times the mean on average.

All measured values
Measured 264-byte random reads, four seconds per run, latencies in µs. Four-reader rows are per-read distributions under load. Internal: 2 GiB zero-filled file; external: the real 94 GiB table.
Device / readersRow p50 (µs)Mean (µs)p99 (µs)p99.9 (µs)Maximum (µs)IOPS
Internal · 1 reader64.361.090.5122.41,09716,280
Internal · 4 readers68.164.1109.0157.51,19961,849
External · 1 reader98.2100.6217.4294.34,7349,883
External · 4 readers98.6121.4170.92,048.136,79032,708

Smaller quants buy space, not speed

Fewer bits per value look like an easy win. A 4-bit row would be 136 bytes instead of 264, and both tables would shrink from 188.8 to about 97 GiB. But the SSD doesn’t care: on the internal drive a 264-byte read had a 64.25 µs median and a 4 KiB read 68.38 µs; on the external drive 98.17 and 99.79 µs. Fifteen times the data barely moved the access time, because the drive fetches a whole page either way.

Table size scales with bytes per row. Read time on SSD doesn’t: a 264 B and a 4 KiB read both took 64–68 µs (internal SSD, p50), and every format here is far smaller than a 4 KiB page.
Row formatRowbytesOne tableGiBBoth tablesGiB
4-bit + scaleshypothetical13648.697.3
8-bit + scalesas shipped here26494.4188.8
16-bithypothetical512183.1366.2

So a harder quant only pays if it changes where a table lives—if a 4-bit Table 0 at about 49 GiB fits in RAM where the 8-bit one at 94 GiB doesn’t. On the same SSD it saves no time and costs quality: every lookup, at every token, gets coarser values. I haven’t measured how much a 4-bit Engram table hurts output, but it’s a trade with nothing on the other side. If disk space is the constraint, buy a bigger SSD. The same logic runs the other way: a 512-byte 16-bit row is still far smaller than a 4 KiB page, so keeping more precision on SSD would cost disk space, not read time.

More readers, more drives?

A second harness ran 8 to 48 concurrent readers on each drive and split across both. With eight readers, splitting four per drive cut the per-read p99 from about 265 µs to about 150 µs, while the median got slightly worse (86 → 93 µs). At 24 readers the ranking reshuffled between repeat runs, and at 48 the median rose to about 235 µs: more outstanding reads mostly mean more queueing. A second drive may help the tail and can keep Engram away from expert-weight streaming. This was a two-drive split, though, and a RAID 0 array might behave differently.

All ten reader configurations
First ten configurations, latencies in µs. A harness round is one read per worker plus Python synchronisation; split means internal plus external SSD. p99 varied by up to about 50% between repeat runs.
Layout / readersPer-read p50 (µs)Per-read p99 (µs)Harness-round p50 (µs)Harness-round p99 (µs)
8 readers · internal only86.1264.8194.8400.9
8 readers · split 4 + 493.4149.6203.6312.3
8 readers · external only103.5171.0226.7346.8
12 readers · internal only88.6185.6247.6504.4
12 readers · external only106.8200.8288.4506.3
12 readers · split 6 + 697.7189.8262.5508.8
24 readers · internal only140.6328.2483.2892.6
24 readers · external only119.4314.3464.3936.5
24 readers · split 12 + 12145.7361.0487.31,102.4
48 readers · split 24 + 24235.3595.0974.41,590.4

Short runs, different file sizes, sustained load and hosts that weren’t fully idle limit how far this generalises, and the same drive may behave differently with another OS or I/O stack. The next useful measurement is a real token-paced fetch alongside the actual competing workload.

5. Remote RAM, Thunderbolt and Ethernet

Memory disaggregation sounds grand; here it just means putting a table in another machine’s RAM and asking it for rows. My test used a small C daemon over TCP, serving a synthetic 4 GiB buffer with one request in flight—transport plus service time, outside any inference engine.

One table fetch, by scheduleLinear scale. A band shows the measured range.
Thunderbolt, one batch
0.092–0.099 ms measured
Thunderbolt, 6 round trips per worker
0.54 ms estimated
External SSD, 4 × 6 reads
0.59 ms derived
1 GbE, one batch
0.6–0.7 ms measured
  • ATable 0 window at 100 t/s (0.25 ms)
  • BTable 0 window at 40 t/s (0.625 ms)

Over a 20 Gb/s Thunderbolt link (TCP, no RDMA), one 24-row batch took 92–99 µs, with a p99 of 139–158 µs; a 48-row batch for both tables took about 100 µs. If each worker instead made six round trips of about 90 µs, a table would take about 0.54 ms—roughly what the external SSD manages. The win comes from one message per table, and the engine has to implement that. With it, Table 0 makes its window up to about 250–270 tokens/s in the model.

Gigabit Ethernet and UDP

Over wired 1 Gb Ethernet, a 24-row batch took 0.60–0.70 ms with TCP and TCP_NODELAY. Serialising 6,336 bytes takes only about 51 µs, and a bulk transfer on the same path reached 117 MB/s, so the time goes into the round trip itself: link, NIC, kernel and service. Energy-efficient Ethernet settings, jumbo frames or 2.5/10 Gb Ethernet might help; I haven’t measured them.

I expected UDP to be faster. It wasn’t: about 0.85 ms against 0.71 ms for TCP in a back-to-back check, with the 6.3 KB reply split into about five IP fragments.

The memory still has to exist somewhere

The donor has to keep the whole table resident, plus room for the OS and the service: 128 GB is about 119.2 GiB, which leaves about 24.8 GiB once a 94.4 GiB table is loaded. You also need access control, matching table versions, timeouts, monitoring and a fallback for when the peer disappears. Remote RAM swaps a capacity problem for a service dependency—so if Table 0 fits in local RAM, put it there.

6. Nine storage paths, compared

Four of these paths are measured or derived; the rest are estimates and assumptions to see what happens as latency grows. “External SSD” means the drive I tested.

One table fetch, nine waysLog scale. Solid: measured or derived. Pale: estimate or assumption.
Local RAM
≈1 µs assumed
Thunderbolt RAM
92–99 µs measured
Fast SSD
≈0.41 ms derived
External SSD
≈0.59 ms derived
1 GbE RAM
0.60–0.70 ms measured
100 MbE RAM
≈1.0 ms estimated
Slow SSD
1.5 ms assumed
Wi-Fi RAM
≈4 ms (2–10 ms) estimated
Spinning disk
≈30 ms assumed
  • ATable 0 window at 100 t/s (0.25 ms)
  • BTable 0 window at 40 t/s (0.625 ms)
  • CTable 1 window at 100 t/s (3.25 ms)
Schedule and evidence for each path
One 24-row table per scenario. Measured values come from standalone harnesses; derived SSD values are six times the four-reader row median. On macOS the token path uses 16-reader batches instead.
Storage / linkOne-table fetchScheduleEvidence
In-memory (same machine)≈1 µsLocal gather assumed; schedule not benchmarkedAssumedIllustrative in-memory latency.
Remote RAM · Thunderbolt92–99 µsOne 24-row TCP batchMeasuredSynthetic 4 GiB buffer; transport plus service. Heatmap uses 95 µs.
Fast local SSD≈0.41 ms4 parallel readers × 6 sequential rowsDerived6 × 68.1 µs four-reader row p50; 2 GiB zero-filled file.
Typical external SSD≈0.59 ms4 parallel readers × 6 sequential rowsDerived6 × 98.6 µs four-reader row p50; real 94 GiB table.
Remote RAM · 1 GbE0.60–0.70 msOne 24-row TCP batchMeasuredSynthetic 4 GiB buffer. Heatmap uses 0.630 ms.
Remote RAM · 100 MbE≈1.0 msOne 24-row batch assumedEstimatedIllustrative estimate for a slower link.
Slower local SSD1.5 ms4 readers × 6 rows assumedAssumedIllustrative slower drive.
Remote RAM · Wi-Fi≈4 ms (2–10 ms)One 24-row batch assumedEstimatedIllustrative; wireless latency varies widely.
Spinning disk≈30 msPer-table scenario; reader schedule unspecifiedAssumedIllustrative per-table latency.

What that does to decode speed

The chapter 3 formula, applied to every path at baseline speeds from 25 to 300 tokens/s.

Scroll sideways for all nine paths; the first column stays put.

  • No stall
  • Some: above 0%, below 30%
  • High: 30% or more
Asynchronous overlap model, one constant fetch latency per column. Large number: resulting tokens/s. Small number: extra token time.
Baselinet/sLocal RAM0.001 msAssumedThunderbolt RAM0.095 msMeasuredFast SSD0.41 msDerivedExternal SSD0.59 msDerived1 GbE RAM0.63 msMeasured100 MbE RAM1 msEstimatedSlow SSD1.5 msAssumedWi-Fi RAM4 msEstimatedSpinning disk30 msAssumed
2525no stall25no stall25no stall25no stall25no stall25no stall25+1.3%23+7.5%12+115%
5050no stall50no stall50no stall50+0.5%50+0.7%49+2.5%48+5.0%43+18%14+265%
7575no stall75no stall75+0.6%74+1.9%73+2.2%71+5.0%69+8.8%59+28%15+415%
100100no stall100no stall98+1.6%97+3.4%96+3.8%93+7.5%89+13%69+45%15+565%
Above 100 t/s: single-stream sensitivity analysis
125125no stall125no stall122+2.6%119+4.9%119+5.4%114+10%108+16%76+65%15+715%
150150no stall150no stall145+3.7%141+6.4%140+7.0%133+13%125+20%81+85%16+865%
175175no stall175no stall167+4.7%162+7.8%161+8.5%152+15%141+24%85+105%16+1,015%
200200no stall200no stall189+5.7%183+9.3%182+10%170+18%157+28%89+125%16+1,165%
225225no stall225no stall211+6.7%203+11%201+12%188+20%170+33%92+145%16+1,315%
250250no stall250no stall232+7.8%223+12%221+13%204+23%179+40%94+165%16+1,465%
275275no stall275+0.1%253+8.8%242+14%239+15%220+25%186+48%96+185%16+1,615%
300300no stall299+0.4%273+9.8%260+15%258+16%235+28%194+55%98+205%16+1,765%

At 100 tokens/s the internal SSD gives about 98 tokens/s and the external one about 97. A 4 ms Wi-Fi round trip drops it to about 69, because it misses both windows. A constant 1.5 ms fetch fits Table 1’s window up to about 217 tokens/s; the 30 ms spinning disk misses it at every speed. The heatmap holds latency constant—the spread from chapter 4 comes on top.

7. What to build, and what to measure next

  1. Place the urgent table first. Local RAM if it fits. Otherwise compare a measured SSD path with a properly batched remote-RAM setup. Capacity and sequential throughput are the wrong ranking.
  2. Protect the read window. Expert streaming, other requests and background I/O all compete for the same drive. A measurement on an idle device says little about a shared production volume.
  3. Measure the whole wait. Record Table 0 and Table 1 completion times, token stalls and tail percentiles. The slowest of four chains matters more than the median row.
  4. Test degraded operation. A remote donor can restart, swap or disappear. Decide whether to fall back, retry or reject the request, and measure what the user sees.
  5. Keep capacity and speed separate. These tables are only one part of model memory. Budget the other weights, attention state, runtime buffers and concurrency headroom too.
  6. Don’t trade quality for disk space. On an SSD a smaller row reads no faster. Quantise the tables harder only if it moves Table 0 into RAM; otherwise keep the precision.

Prefill, speculation and batches change the workload

Prefill hashes and reads many prompt positions in one wide sweep. A speculative verification pass with k draft tokens covers k+1 positions and requests up to (k+1) × 48 rows; a serving batch multiplies that again. Draft tokens are known before verification, so an engine could prefetch their rows while drafting—an idea I haven’t measured.

The two measurements I’d do next: a token-paced trace of DwarfStar’s asynchronous reader, with expert streaming running alongside, and the synchronous F on a Mac, since that’s the time every token pays there today.

Sources, data and limits

Architecture and reader scheduling refer to DwarfStar at commit ee7e840, an inference engine for DeepSeek V4.1 Flash. See also the model configuration and DwarfStar model card; those two links point to main branches and may change.

The measurements come from my standalone storage harnesses, run on 25 October 2026. You can download the recorded SSD and split-disk measurements at their original precision, with local paths removed; the network samples aren’t included.

Size the system around the workload.

At Capacity, we help teams build private AI systems around their data and operating constraints. Bring us the model, the hardware budget and the response time your users need, and we’ll help turn them into a deployment you can test.

Talk to Andreas hello@capacity.at
Back to the blog