Scaling LLM-Based Ranking Systems with Prefill-Only Optimization
linkedin · Tech · 2026 · source Agentic: no · promotional bias: low · source-backed · extracted with prompt 0.5.6 (schema v2)
Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.
Problem
Domain: LLM ranking inference
LinkedIn needed to serve LLM-based ranking for AI Job Search and AI People Search, scoring many candidates per query under strict P99 latency constraints.
Constraints:
- Ranking workloads require prefill-only scoring rather than autoregressive generation.
- P99 latency had to stay within a few hundred milliseconds under load.
- CPU-side serialization, decode-loop overhead, prefix recomputation, and Python runtime behavior all limited throughput.
Architecture
LinkedIn adapted SGLang for prefill-only ranking through staged optimization: batch tokenization, preserving batch boundaries, a scoring-only fast path, reduced CPU/GPU synchronization, in-batch prefix caching, multi-process gRPC serving, and multi-process scheduling.
Diagram confidence: explicit (topology described by the source).
flowchart LR A["Ranking request"] --> B["Batch tokenizer"] B --> C["Batch send transport"] C --> D["SGLang scheduler"] D --> E["Scoring-only fast path"] E --> F["In-batch prefix cache"] G["Python gRPC server"] --> H["Multi-process gRPC servicers"] H --> I["Multi-process scheduler workers"] I --> D
Components
| Component | Role | Interacts with |
|---|---|---|
Ranking request |
Query/member context plus many candidate-item prompts to score. | Batch tokenizer |
Batch tokenizer |
Tokenizes many prompts concurrently instead of serially. | Ranking request, Batch send transport |
Batch send transport |
Preserves tokenized batch structure over ZMQ to the scheduler. | Batch tokenizer, SGLang scheduler |
SGLang scheduler |
Builds prefill batches and dispatches inference work. | Batch send transport, Scoring-only fast path, Multi-process scheduler workers |
Scoring-only fast path |
Runs prefill and final-logit scoring without decode, sampling, or unnecessary logprob extraction. | SGLang scheduler, In-batch prefix cache |
In-batch prefix cache |
Reuses shared query-prefix KV within a single forward pass. | Scoring-only fast path |
Python gRPC server |
Handles request parsing, access validation, metrics, logging, and tracing. | Multi-process gRPC servicers |
Multi-process gRPC servicers |
Parallelizes request preprocessing and network I/O beyond one Python process. | Python gRPC server, Multi-process scheduler workers |
Multi-process scheduler workers |
Parallel scheduler processes per GPU to remove CPU scheduling bottlenecks. | Multi-process gRPC servicers, SGLang scheduler |
Data flow
A ranking request contains a query/member context prefix plus many item-specific suffixes. Prompts are tokenized in batch, transmitted as one batch to the scheduler, scored through a prefill-only path that returns final-token logits without decode/sampling, reuses shared prefix KV within the batch, and passes through multi-process gRPC and SGLang schedulers to keep CPU and GPU work pipelined.
3 supporting quotes
Why this architecture
LinkedIn optimized for the real critical path of ranking rather than generic text generation, preserving semantic equivalence while removing decode, CPU serialization, redundant prefix work, and Python runtime bottlenecks.
3 supporting quotes
Models used: Embedding-0.6B · 0.6B decoder-only ranker · 0.4B pruned ranking model · 375M decoder-only ranker · SGLang
Scale
- End-to-end P99 latency needed to stay within a few hundred milliseconds.“End-to-end P99 latency must stay within a few hundred milliseconds under load.”article, stated
- Batch tokenization reduced P99 latency from 4583 ms to 464 ms for an Embedding-0.6B workload.“P99 latency dropped from 4583 ms to 464 ms — roughly 10× faster.”article, stated
- Batch send reduced average latency from 70.39 ms to 41.12 ms per request.“this change reduced average latency from 70.39 ms to 41.12 ms per request—a 41.5% reduction”article, stated
- The scoring path reduced P99 latency from 6220 ms to 454 ms and increased throughput by about 25%.“P99 latency dropped from 6220 ms to 454 ms (13.7×), while throughput increased by ~25%”article, stated
- The final results were measured on H100 GPUs under P99 latency of at most 500 ms.“All results are measured on H100 GPUs under a p99 latency ≤ 500 ms”article, stated
Alternatives considered (roads not taken)
Generic generation path for ranking
Rejected because: Decode and sampling work are unnecessary for prefill-only relevance scoring.
Rely on client-side batching alone
Rejected because: The tokenizer manager fragmented batch structure before the scheduler.
Multi-Item Scoring with item-aware masking
Rejected because: In-batch prefix caching preserved standard batched inputs and avoided specialized kernel-level masking.
Patterns
latency-optimization (production-operations)
LinkedIn removed serial CPU work, decode overhead, synchronization gaps, redundant prefix computation, and Python bottlenecks to meet P99 latency targets.
semantic-caching (inference)
In-batch prefix caching reuses shared query-prefix KV for all items in a ranking batch.
observability-tracing (production-operations)
Profiling and gRPC observability exposed whether bottlenecks were in tokenization, GPU execution, scheduling, or Python runtime behavior.
structured-output-contract (model-interface)
The specialized scoring API treats ranking as a first-class path that returns relevance logits instead of generated tokens.
Tradeoffs
Ranking execution path
Chose specialized prefill-only scoring path over standard generative decode path.
Rationale: Ranking only needs final-token logits, so skipping decode and sampling removes unnecessary overhead while preserving scoring semantics.
Prefix amortization technique
Chose in-batch prefix caching over specialized Multi-Item Scoring kernels for this focus.
Rationale: In-batch prefix caching kept standard batch structure while reusing shared prefix KV.
Python serving architecture
Chose multi-process servicers and scheduler workers over single Python process handling preprocessing and scheduling.
Rationale: Multiprocessing scaled CPU-side work with available cores while keeping GPU execution fed.
Gotchas (what bit them)
Tokenization serialization consumed hundreds of milliseconds before GPU work started.
Root cause: Prompts were tokenized one at a time on the CPU.
Resolution: Enable batch tokenization and dynamic async batch tokenization.
Tokenized batches fragmented before reaching the scheduler.
Root cause: The tokenizer manager sent prompts individually over ZMQ.
Resolution: Introduce batch send so the scheduler executes the full batch in one GPU prefill pass.
Python runtime pauses became a P99 latency problem.
Root cause: Garbage collection and GIL contention paused request handling and preprocessing.
Resolution: Use multi-process gRPC serving and scheduler workers.
Evaluation
LinkedIn evaluates with profiling, PyTorch traces, throughput/latency benchmarks, H100 P99 latency constraints, semantic equivalence to generation, and production relevance for AI Job Search and AI People Search.
Metrics: P99 latency · throughput · items per second per GPU · average latency · CPU/GPU synchronization gaps · GPU utilization
Outcomes
- Batch tokenization reduced P99 latency roughly 10x for an embedding workload.
- Batch send reduced average latency by 41.5% for a 0.6B ranking workload.
- The scoring path reduced P99 latency from 6220 ms to 454 ms and increased throughput by about 25%.
- Multi-process serving delivered an additional roughly 40% throughput increase.
- The optimizations power AI Job Search and AI People Search for millions of LinkedIn members.
The article is unusually specific about optimization stages and benchmark measurements, making this a strong latency-optimization case.