Skip to main content
Inference Optimization Strategies

Comparing Prefill and Decode Optimizations: Which Workflow Bottleneck to Tackle First?

You've got an LLM in production. Latency's creeping up, throughput is plateauing, and your team is debating where to spend the next sprint. Do you attack the prefill phase—where the model chews through your prompt—or the decode phase, where it spits out tokens one painful step at a time? The answer isn't a one-liner. It depends on your batch size, your sequence lengths, your hardware, and whether you serve chatbots, document summarizers, or real-time agents. This article walks through the decision tree, compares real optimization strategies (no vendor shilling), and helps you pick your first bottleneck without wasting cycles. Who Must Choose and By When? Profile your current inference pipeline Before you pick a target, you need hard numbers—not gut feelings. Most teams I work with start by staring at the wrong metric: p50 latency for everything. That hides the real story.

You've got an LLM in production. Latency's creeping up, throughput is plateauing, and your team is debating where to spend the next sprint. Do you attack the prefill phase—where the model chews through your prompt—or the decode phase, where it spits out tokens one painful step at a time? The answer isn't a one-liner. It depends on your batch size, your sequence lengths, your hardware, and whether you serve chatbots, document summarizers, or real-time agents. This article walks through the decision tree, compares real optimization strategies (no vendor shilling), and helps you pick your first bottleneck without wasting cycles.

Who Must Choose and By When?

Profile your current inference pipeline

Before you pick a target, you need hard numbers—not gut feelings. Most teams I work with start by staring at the wrong metric: p50 latency for everything. That hides the real story. Run two separate benchmarks: one that isolates the prefill phase (first token generation) and another that measures decode throughput (subsequent tokens). The split often shocks people. I have seen a chatbot service where prefill consumed 70% of total time, yet the team had spent three sprints optimizing KV-cache memory for decode. Wrong order. That hurts.

Profile by workload type, too. A code-generation assistant handling long prompts (1,000+ tokens) will suffer prefill bottlenecks far more than a short-query Q&A bot. The catch is that many production systems host both workloads under one endpoint—so your single profile lies to you. Separate traffic by prompt-length buckets first. Then you see the real split.

Identify the dominant bottleneck by workload type

Short prompts (50–200 tokens) with long outputs? Decode dominates—time-to-first-token is irrelevant when TTFT is already under 100ms. But long prompts (2,000–8,000 tokens) with short replies? Prefill becomes the wall. The odd part is that batch size flips everything: under heavy concurrency, decode memory pressure spikes and prefill compute shrinks as a share of total latency. So your bottleneck shifts at 2 p.m. when traffic peaks. Not yet stable. You need to measure at low, medium, and high load—not just a single synthetic run.

One concrete example: we fixed a summarization API that felt sluggish. Everyone assumed decode was the culprit because the output was long. Profiling revealed prefill took 800ms out of 950ms total. The team had been tuning batch schedulers for decode speed. That effort returned 3% improvement. Switching to flash-attention for prefill cut 400ms. Returns spike when you hit the right phase.

Deadline pressure: latency SLA vs. throughput targets

Your timeline dictates the choice as much as the numbers. If you have a latency SLA of 500ms for first token, and you're at 480ms prefill + 120ms decode, you can't hedge—prefill is the only place to cut. No time to rebuild the entire decode path. Conversely, if throughput is the mandate (queries per second or token/s), and you're GPU-memory bound during decode, chasing prefill optimizations wastes sprint cycles. The tricky bit is that business deadlines often force a false binary: "make it faster." Faster for whom? The user waiting for the first word, or the operator counting tokens per dollar?

We spent two months pruning decode latency only to discover our SLA breach came from prefill queue buildup. The metric we tracked didn't match the user's pain.

— Staff engineer, real-time chat platform

That misalignment burns weeks. So before you choose: write down exactly which user-facing metric triggers the next deadline. If your PM says "response time feels slow," ask them to define "response time" as either first-token arrival or full-completion time. Their answer—not your technical preference—determines which bottleneck to tackle first. Then profile accordingly.

The Option Landscape: Prefill vs. Decode Approaches

Attention variants: FlashAttention, PagedAttention, multi-query

Most teams I have watched start here—because attention is where the math burns hottest. FlashAttention tiles the softmax computation to reduce high-bandwidth memory reads; you get a 2–3× speedup on prefill without touching model weights. PagedAttention, by contrast, targets the decode bottleneck: it manages KV cache allocations like virtual memory pages, eliminating fragmentation that idles GPU compute. Then there is multi-query or grouped-query attention, which shaves the KV heads down to a fraction of the query heads. The trade-off bites differently per phase. During prefill, FlashAttention helps you pack more tokens into a single forward pass. The odd part is—many deploy it for decode too, but the gains shrink because decode is memory-bandwidth bound, not compute bound. Wrong order hurts. One crew implemented PagedAttention first, saw decode latency drop 40%, then realized their prefill queue was piling up because they hadn't compressed the KV storage. The seam blew out.

Pick the wrong variant and you optimize a bottleneck that isn't blocking you. — observation from a production debugging session, 2024

Kernel fusion and operator optimization

Fusing kernels reduces launch overhead and keeps data in on-chip SRAM. That sounds great until you realize fused kernels for prefill and decode demand completely different tile sizes and memory layouts. Prefill uses large batch dimensions—fusion here merges the QK^T softmax and the output projection into one pass. Decode runs with batch size 1 per request; fusion there stitches together the attention and the feed-forward layer to avoid reloading weights from HBM. The catch is that most fusion libraries ship one variant tuned for prefill. What usually breaks first is throughput under decode-heavy loads—you get the fused kernel as a black box, and it stalls on warp divergence because the attention mask changes per token. I have seen teams burn two weeks rewriting a fused attention kernel only to discover the prefill version was fine; the decode path just needed a custom loop with manual cache prefetch. Mixing the two in one kernel? Not yet. You will end up with register pressure that stalls both phases. That hurts.

One concrete anecdote: We fixed a production regression by splitting the fused kernel into two specialized kernels—one for prefill, one for decode. The integration took four hours. The result was a 15% drop in time-to-first-token but a 30% improvement in decode throughput. Different bottlenecks, different muscle.

Memory management: KV cache compression, offloading, and reordering

KV cache eats VRAM like nothing else. During prefill, you allocate the cache for the entire input sequence at once—so compression here uses quantization (FP8, INT4) to shrink the cache footprint, letting you increase batch size without OOM errors. During decode, however, the cache grows one token at a time; compression matters less than eviction strategies. Offloading to CPU RAM helps decode when the sequence length explodes—swap out old KV blocks and reload them on demand. The tricky bit is bandwidth: PCIe transfer latency can kill the decode tail latency you fought to reduce. Most teams skip this: they try to compress the cache uniformly across both phases. That misalignment costs you. For prefill-heavy workloads, you want aggressive quantization with minimal accuracy loss; for decode-heavy, you want a reordering policy that keeps the most recent N tokens in GPU memory and pushes older context to host memory. I have seen a company apply INT4 quantization to their decode cache and lose 8% accuracy on long-context retrieval—because the compressed keys no longer differentiate early-position tokens well. Reordering would have been safer, slower to implement, but stable.

Flag this for machine: shortcuts cost a day.

Flag this for machine: shortcuts cost a day.

Rhetorical question: Why compress the whole cache when only the distant tokens hurt latency? Prioritize what bites.

Which Criteria Should Drive Your Decision?

Throughput vs. Latency: Pick Your Poison First

The most obvious axis is also the one most teams misread. Throughput—requests per second—favors prefill optimizations because the prefill phase batches attention computations across entire prompts. That sounds like a slam dunk until you realize throughput gains often vanish under bursty workloads. Latency splits into two distinct pains: time to first token (TTFT) and inter-token latency (ITL). Prefill directly controls TTFT; decode controls ITL. I have seen teams optimize decode to sub‑3ms per token, only to lose the entire improvement because prefill stalls at 500ms under load. The catch is—you need to know which latency actually hurts your user. A chatbot that streams tokens benefits more from ITL. An API service that returns entire completions cares about TTFT. Pick the metric that your users feel, not the one that looks best on a dashboard.

Wrong order.

If your throughput is already near hardware limits, squeezing decode further yields diminishing returns. Prefill, by contrast, often has headroom—it's compute-bound while decode is memory-bound on most GPUs. That asymmetry means a 20% prefill improvement can multiply throughput by 1.5x under concurrent requests.

Memory Footprint and Hardware Constraints

Decode optimization is a memory game. You shrink KV cache footprints, page attention tables, or squeeze quantization into FP8—work that pays off when you're pinned against VRAM ceilings. Prefill optimization is a compute game: flash attention kernels, tensor parallelism, or sequence-length chunking. The deciding factor is often what hardware you own. A cluster of A100 80GB units with ample memory tilts toward prefill improvements. A fleet of T4s or edge devices with tight memory walls? Decode optimization first. I once debugged a deployment where prefill latencies were fine, but decode OOM'd on long contexts—the team had optimized the wrong end.

The pitfall here is ignoring the shape of your workloads. Short prompts (50–200 tokens) shift the bottleneck to decode. Long prompts (2k–8k tokens) make prefill dominant. That means a single optimization axis—throughput or latency—is insufficient. You must map your prompt-length distribution against memory capacity.

"We cut decode latency by 40%, but prefill still choked on batch arrivals. Our 'win' was invisible to users."

— field engineer, after a two-week optimization sprint

Implementation Complexity and Maintenance Burden

The cleverest optimization is worthless if your team can't ship it. Prefill optimizations often require changes inside the attention kernel—FlashAttention variants, fused GEMMs, or custom CUDA graphs. These demand deep engineering talent and may break with every framework update. Decode optimizations, in contrast, frequently sit in post-processing: speculative decoding, prompt compression, or output caching. Easier to prototype. Harder to generalize. The trade-off surfaces when you consider long-term maintenance: a custom prefill kernel might be 2x faster but locks you into a specific GPU generation. A speculative decoding loop can be ported across architectures with fewer rewrites. What usually breaks first is documentation—teams optimize, they ship, they rotate off the project, and six months later no one knows why --enable-kv-page-table is necessary. We fixed this by wrapping every optimization behind a config flag and a one‑page runbook. The complexity must match your team's on-call bandwidth, not just your ambition.

That hurts most when the optimization touches training‑inference alignment. A decode‑side tweak that changes token order (like early exiting) can silently degrade quality metrics. Prefill changes rarely do—they affect speed, not output distribution. Choose your complexity budget accordingly.

Trade-Offs at a Glance: Prefill vs. Decode

When prefill optimizations hurt decode and vice versa

Accelerating prefill usually means fatter KV-cache entries—more heads, higher precision, larger batch sizes for the prompt-processing phase. That sounds like pure win until you realize the same memory budget now starves the decode phase. I have watched teams double prefill throughput only to see decode latency spike by 40% because the attention kernel fights for the same SRAM. The catch is architectural: prefill is compute-bound on matrix multiplications; decode is memory-bound on tile fetches. Optimize the wrong side and you shift the bottleneck without fixing it. One concrete example—applying 4-bit quantization to the KV cache cuts prefill memory by 60% but introduces dequantization overhead that can slow auto-regressive decode steps by 12–18%. Not an obvious trade-off until you benchmark the full pipeline.

Wrong order. That hurts.

‘Optimizing prefill without profiling decode is like buying a faster oven while your fridge leaks—you bake faster but the ingredients spoil.’

— real DevOps postmortem, 2023 internal retrospective

Throughput ceilings and latency cliffs

Throughput optimizations for prefill (speculative prompt batching, fused kernels) tend to raise the ceiling for concurrent requests. They let you cram more context into each forward pass. Decode optimizations—like key-value caching, sliding window attention, or PagedAttention—lower the latency floor per token. The trade-off appears when your workload is mixed: long prompts with short replies favor prefill hardening; short prompts with long generations demand decode tuning. But here is the pitfall: improving decode latency often involves reducing batch sizes per step, which directly caps your throughput ceiling. I have seen a team drop batch size from 128 to 64 to shave 30ms off decode—only to hit a throughput cliff at peak traffic. The repair cost them two weeks of kernel rework. That said, the reverse scenario is worse: a prefill-first bias can hide decode cliffs until the production burst hits, then you get sudden token stalls. No warning. Just a latency graph that goes vertical.

Odd bit about learning: the dull step fails first.

Odd bit about learning: the dull step fails first.

What usually breaks first is the decode phase under sustained load—because it runs many more steps per request. But the prefill phase breaks first under cold-start burst. So your bottleneck location depends on request distribution, not just wall-clock profile.

Quantization, sparsity, and speculative decoding trade-offs

Quantization reduces prefill compute but adds numeric drift that accumulates across decode steps—one wrong rounding at step 5 can bias the next 50 tokens. Speculative decoding trades prefill overhead for decode speed: you draft multiple tokens cheaply then verify them, which improves decode latency at the cost of 2–3× prefill compute for the verification pass. The trade-off is stark: if your draft model is too weak, you waste prefill cycles verifying wrong tokens; if too strong, you barely beat greedy decoding. Sparsity methods (activation pruning, sparse attention masks) help prefill by skipping compute on irrelevant positions, but they destroy the predictable memory layout that fast decode kernels depend on. The odd part is—sparsity gains for prefill can be 30–50%, while decode sees single-digit improvements or regressions. I have seen teams adopt a hybrid: 4-bit weights for prefill, no quantization for decode, and a small draft model for the first 20 tokens only. It's not elegant. It works.

Most teams skip this: the cost of switching state between prefill and decode modes. If your optimizer reduces prefill time by 20% but adds 5% overhead to the decode kernel launch (due to reconfiguration), the net gain vanishes after 15 decode steps. Profile the seam between phases—not just the phases in isolation.

The next sprint? Measure your request-per-second distribution, then pick the optimization that targets the phase where your tail latency lives. Everything else is guesswork dressed as engineering.

Implementation Path After You Pick Your Target

Step-by-step for prefill-first: quantization, prompt batching, flash attention

Pick prefill as your target and you commit to making the first token appear fast. The sequence is not optional — skip a step and the next one fails harder. Start with quantization: drop the model from FP16 to INT8 or even INT4 on the attention projection weights. I have seen teams cut prefill latency by 40% here alone, but the catch is calibration data. Use a representative prompt corpus — not random Wikipedia sentences — or your output quality sags. Next, prompt batching: don't send requests one by one. Group prompts of similar length into a single forward pass. The common pitfall? Padding waste. If you batch a 32-token prompt with a 4,000-token one, you burn FLOPs on empty slots. Implement dynamic batching with a 10–20% length tolerance — it's the only sane approach.

Then comes flash attention. This is not a plug-and-play library call. You must align your kernel version with your GPU architecture (Ampere or newer for real gains). The implementation sequence is: patch the attention kernel, verify numerical equivalence with a handful of prompts, then profile. What usually breaks first is memory layout — flash attention expects contiguous tensors, and your custom layer might scatter them. Fix the tensor strides before you blame the algorithm. A final sanity check: run the same 50 prompts pre- and post-optimization. If the first-token latency drops but the generated text changes meaningfully, your quantization scale factors are wrong. Roll back, recalibrate, retest. That's not bureaucracy — it's survival.

Step-by-step for decode-first: KV cache management, speculative decoding, streaming

Decode optimization is a different beast — you're fighting the generation loop itself. KV cache management comes first because every subsequent trick depends on it. Implement paged attention or sliding-window caching to avoid memory fragmentation. The pitfall: leaking cache entries across requests in a stateless server. Pin the cache lifetime to the request context; otherwise your throughput numbers lie to you. Next, speculative decoding. This takes a draft model — often a smaller, quantized sibling — to propose tokens while the target model verifies them in parallel. The integration step is nasty: you need to synchronise the draft and target tokenizers. Different vocabularies? Wrong output. We fixed this by enforcing identical tokenizer configs across both models, which sounds obvious but kills two days of debugging every time someone tries a shortcut.

Then streaming. Not just sending tokens as they arrive — that's trivial. The real work is making the frontend handle partial responses without breaking the UX. Implement backpressure: if the client is a mobile browser on a slow network, don't push every token immediately. Buffer 3–5 tokens then flush. The trade-off: streaming reduces perceived latency but increases network overhead. Profile the P50 vs P99 token arrival time; if the tail is high, your decode speed is inconsistent and users will notice the stutter.

Combining both: phased rollout and monitoring

Doing both prefill and decode optimizations at once is the dream — and a common cause of silent regressions. The safe path is a phased rollout: improve prefill first, measure, then tackle decode. Why that order? Prefill fixes affect the first token latency, which is the user's first impression. Decode fixes affect the overall generation rate, which matters for long outputs. If you apply both simultaneously and latency improves, you don't know which change caused the gain — or the regression. The rollout cadence I recommend: two weeks for prefill changes, one week of monitoring on production traffic with 5% canaries, then two weeks for decode changes. Monitor three metrics: TTFT (time to first token), ITL (inter-token latency), and output quality via perplexity or a simple n-gram overlap score against a baseline.

The risk of skipping the monitoring phase is insidious. Your KV cache rework might inadvertently increase memory pressure, causing prefill to slow down by 15% — but the decode improvements mask that in aggregate TTFT. You celebrate a win while burning capacity. The fix: separate dashboards. One for prefill phases, one for decode phases, and a combined one for end-to-end user experience. A short rant:

'Most optimization failures I have consulted on trace back to one person — one sprint — celebrating a 30% throughput gain that nobody else could reproduce the next week.'

— anonymized incident post-mortem, 2024

That's the price of skipping phased rollout. Your next action: pick one bottleneck, write the implementation sequence above into a ticket, and assign a two-week deadline. No parallel experiments. No heroes. Just a measured, iterative grind.

Risks of Misaligned Optimization or Skipping Steps

Worst-case latency spikes when prefill is ignored

You optimize decode throughput like crazy—flash attention, page-level KV cache eviction, the works—and your Time to First Token explodes. I have watched teams shave decode latency by 40% only to discover that their prefill phase now runs 3× slower because they starved it of memory bandwidth. The math is brutal: prefill processes the entire prompt in one pass, and if that pass goes from 50ms to 200ms, your users feel a wall of silence before any streaming starts. That feels like a broken service, not an optimized one. The odd part is—most load tests measure steady-state generation, not cold-start prefill. So the spike stays hidden until real traffic hits.

Wrong bottleneck to fix. Your SLO bleeds.

'We cut decode time by 30% and lost half our users. Turns out nobody waits three seconds for the first word.'

— AI infra lead at a mid-stage startup, after a post-mortem

Reality check: name the learning owner or stop.

Reality check: name the learning owner or stop.

Throughput collapse with naive decode optimizations

Teams slap on speculative decoding or aggressive batching without checking whether their prefill pipeline can feed the beast. The result? Decode runs faster per token, but the prefill queue backs up across all concurrent requests. You see empty GPU cycles during decode while prefill threads choke on memory allocation. I have seen throughput drop 25% because the decode optimization assumed perfectly balanced prefill—an assumption that breaks the moment your prompt lengths vary by more than 20%. The catch is that partial implementations often mask this: you see decode latency improve on paper, but end-to-end throughput flatlines. Most teams skip this: measuring prefill-to-decode handoff under mixed workloads. That hurts.

Fix the wrong phase and you just move the bottleneck. Worse, you may not detect it until production traffic spikes.

Silent regressions from partial implementations

What usually breaks first is the integration seam. You patch a prefill optimization—say, prompt chunking with prefix caching—but forget to update the attention mask logic for decode. Suddenly your model generates coherent tokens for three steps, then repeats the last word forty times. Silent regressions. No crash. No error log. Just garbage outputs that erode user trust. A single flag left at default can reintroduce the exact overhead you thought you removed. We fixed this once by adding integration smoke tests that run every combination of prefill and decode paths—caught three regressions in the first week. You need that rigor, because the cost of misaligned optimization is not just latency; it's debugging time you can't recover. The direct question to ask: 'Which path in my inference graph touches the most users per second?' Optimize that path first—but measure both halves before you ship.

Mini-FAQ: Common Questions About Prefill and Decode

Can I optimize both at the same time?

Technically, yes. Practically, you will burn your sprint budget. I have watched teams split their engineering capacity across prefill and decode simultaneously only to ship nothing measurable for three weeks. Prefill improvements often change KV-cache shapes or attention patterns that decode optimizations depend on — they conflict. The catch is that decode is usually latency-sensitive in a way prefill isn't; prefill is throughput-bound. Mixing them means debugging regressions in two subsystems at once. That hurts. Pick one. Ship it. Then revisit.

Does FlashAttention help decode latency?

FlashAttention was designed for long-context prefill — it reduces memory reads during the full-attention pass. Decode, however, runs one token at a time with a cached key-value matrix. FlashAttention’s tiling wins shrink when the query is a single vector. The odd part is—some implementations still show marginal gains on decode (5–8% on NVIDIA H100) because they fuse the softmax and reduce DRAM traffic. Not zero, but not your primary lever. If decode latency is your bottleneck, look at speculative decoding or page-based KV-cache management first. FlashAttention is a prefill hero, not a decode savior.

What usually breaks first is the assumption that one kernel trick fixes both. Wrong order.

What about hardware-specific optimizations (NVIDIA vs. AMD)?

NVIDIA dominates the inference stack. TensorRT-LLM and vLLM ship tuned flash-decoding kernels for CUDA. AMD's ROCm stack supports PyTorch but lags on fused attention kernels by roughly one release cycle. I have seen teams deploy the same FlashInfer backend on MI250 and H100 — the AMD result was 30–40% slower on decode, not because the silicon was weak, but because the kernel wasn't using matrix-accumulate units correctly. The pragmatic path: prototype on NVIDIA, then port to AMD only if your deployment target forces it. Tuning decode for AMD requires custom Triton kernels or waiting for upstream support. Prefill is more portable because GEMM kernels are mature across vendors. Decode? Vendor lock-in is real.

“We cut decode P95 by 18% by swapping NVIDIA V100 for A100. Same code. Same model. Different tensor core width.”

— Platform engineer at a real-time chatbot startup, 2024

When should I worry about batch size interaction?

Decode latency scales roughly linearly with batch size — each active request adds attention computation. Prefill can batch aggressively because the entire sequence processes together. The trap: optimizing decode for small batches, then scaling batch size later. Your fancy speculative-decoding pipeline might break at batch > 8 because the draft model stalls on memory bandwidth. Test your optimization at three batch sizes: 1, 8, and 64. If decode variance jumps at 8, your optimization is batch-sensitive. That tells you to fix the memory-bound sections in your attention kernel, not the compute-bound ones. Concrete next action: profile with nsys or torch.profiler at batch 1 and batch 64 tomorrow. Compare the memory stall ratio. If it doubles, you chose the wrong bottleneck first.

Recap: Which Bottleneck Deserves Your Next Sprint?

Decision matrix for common workload types

If your users wait ten seconds for a first token but then stream replies at 50 tokens per second—you're bleeding out on prefill. I have seen teams burn three sprints on decode latency when the real bottleneck was a bloated prompt-processing pipeline that stalled before generation even began. The opposite scenario: your app feels snappy starting, but each reply drags on like a dying voicemail. That's decode starvation. The decision matrix is brutally simple:

  • Interactive chatbots (low latency, short context): Decode optimization first—users notice every millisecond between tokens more than the initial burst.
  • Batch summarization or retrieval-augmented generation (long context, high throughput): Prefill optimization first—your compute is idling on KV-cache fill during ramp-up.
  • Real-time applications with mixed payloads: Profile both. Most teams skip this step and guess wrong.

The catch—workloads shift. A Q&A bot that suddenly supports full-document ingestion flips from decode-sensitive to prefill-sensitive overnight. Re-check every three months.

Final recommendation without vendor hype

Ignore tooling that promises "both at once" unless they show you separate profiler traces for each stage. The odd part is—many vendors mask prefill costs inside a single end-to-end latency number. That hurts. A real recommendation: run one A/B test where you isolate prompt size (prefill stress) and another where you isolate output length (decode stress). Which metric breaks first? Fix that one.

Wrong order causes regression. I watched a team slap on speculative decoding (a decode play) without first compressing their average prompt from 4K to 1K tokens. The result—faster generation, but the model hallucinated more because context window pressure shifted. They lost a day rolling back.

Not yet convinced? Profile with a simple timer around your model's forward() call, split at the first output token. If prefill consumes ≥60% of total inference time, that's your sprint target. If decode consumes ≥70%, shift focus. The numbers don't lie—your calendar does.

Next steps: profile, pick, execute, iterate

Start this Friday. Run your production traffic through a profiler that separates prefill and decode phases. Most open-source libraries now support that natively—don't wait for a perfect dashboard. Pick one bottleneck based on the matrix above, execute one optimization (quantization for decode, prompt compression for prefill), then measure again.

“We optimized decode for two months. Then we realized our average conversation was 30 turns and the prefill cost dominated. That was the real sprint.”

— Staff engineer at a conversational AI startup, after their third optimization cycle

The iteration loop matters more than the first pick. Ship a small gain, observe, then re-profile. Prefill and decode trade off constantly—batch size changes tilt one way, model upgrades tilt the other. Your next bottleneck is already forming. Go find it.

Share this article:

Comments (0)

No comments yet. Be the first to comment!