Section C · Coding

Coding Fundamentals

Language choice, the DSA patterns that actually appear in infra rounds, async basics for the right kind of "I/O-bound" problem, and the code-style signals senior reviewers look for.

Picking a language for the live round

The JD names Python first and lists C++, Rust, Go, CUDA as nice-to-haves. For the coding round, the default is Python unless you're explicitly told otherwise. Reasons:

  • Most infra tooling tasks at the company will be Python or Go.
  • Interviewers grade on clarity and reasoning; Python lets you express the algorithm without language ceremony.
  • If you're strongest in another language, say so explicitly and use it — the worst outcome is fumbling syntax in Python because you're a Go native.

For deep-system questions (kernel bypass, lock-free queues), C++ or Rust may come out naturally. Don't force it; let it come.

Python — the lingua franca

For this role, "Python" in practice means:

  • Standard library fluency — collections, heapq, itertools, asyncio, concurrent.futures, contextlib, dataclasses.
  • HTTP clients — httpx for async, requests for sync.
  • Numerical — numpy at a comfort level. Maybe pandas.
  • Async — asyncio for I/O concurrency.
  • Subprocess and OS — subprocess, os, pathlib.
  • Type hints — use them by default for senior code reviews.
# The shape of senior Python you should produce by reflex
from __future__ import annotations
from dataclasses import dataclass
from collections import deque
from typing import Iterable

@dataclass(slots=True)
class Request:
    id: str
    prompt_tokens: int
    deadline_ms: int

class TokenRateLimiter:
    """Token-bucket rate limiter; thread-safe outer use assumed monotonic."""
    def __init__(self, capacity: int, refill_per_sec: float) -> None:
        self.capacity = capacity
        self.refill = refill_per_sec
        self._tokens = float(capacity)
        self._last_ts = 0.0

    def allow(self, now: float, cost: int = 1) -> bool:
        self._tokens = min(
            self.capacity,
            self._tokens + (now - self._last_ts) * self.refill,
        )
        self._last_ts = now
        if self._tokens >= cost:
            self._tokens -= cost
            return True
        return False

Notice: type hints, dataclass(slots=True) for performance + clarity, from __future__ import annotations, one clear public method.

Systems languages — C++, Rust, Go

You won't be asked to write 200 lines of C++ in a 45-minute round, but you should be able to discuss why these languages show up in GPU infrastructure.

LanguageWhere it lives in this stack
C++CUDA kernels, custom inference servers, Triton backends, integration with cuDNN/NCCL/TRT, anything inside vLLM's hot path
CUDAThe kernel language for NVIDIA GPUs. Knowing how a kernel launches, what shared memory and registers are, is a senior signal even if you don't write CUDA daily.
RustNew control-plane services, network proxies, observability collectors. Increasingly used in adjacent infra (Tokio for async, Axum for services). Some inference layers (text-generation-inference) are Rust.
GoKubernetes ecosystem — operators, CRD controllers, kubelet extensions, networking plugins. If you write a custom scheduler extender, you'll write Go.
// A minimal Rust sketch — async queue worker for a request pool.
// You wouldn't be asked to write this from scratch in an interview,
// but you should be able to discuss the shape.
use tokio::sync::Semaphore;
use std::sync::Arc;

async fn run_worker(
    queue: Arc>,
    limit: Arc,
    backend: Arc,
) {
    while let Ok(req) = queue.recv().await {
        let permit = limit.clone().acquire_owned().await.unwrap();
        let backend = backend.clone();
        tokio::spawn(async move {
            let _p = permit;
            backend.handle(req).await;
        });
    }
}

Async patterns — when they matter, when they don't

Async is the right tool when:

  • You're orchestrating many concurrent I/O operations (HTTP fan-out, multiple downstream services, streaming).
  • You're building a gateway, router, or sidecar that holds many open connections.
  • You're consuming a high-rate event stream.

Async is not the right tool when:

  • Your work is CPU-bound. Async doesn't help; use processes or threads with the GIL released by the underlying lib.
  • You need parallelism on multi-core, not concurrency.
# The shape of async you might be asked to write —
# fan out N inference calls with a concurrency cap.
import asyncio
import httpx

async def fan_out(prompts: list[str], url: str, max_in_flight: int = 16):
    sem = asyncio.Semaphore(max_in_flight)
    results: list[str | None] = [None] * len(prompts)
    async with httpx.AsyncClient(timeout=60.0) as client:
        async def one(i: int, prompt: str) -> None:
            async with sem:
                try:
                    r = await client.post(url, json={"prompt": prompt})
                    results[i] = r.json()["text"]
                except httpx.HTTPError:
                    results[i] = None
        await asyncio.gather(*[one(i, p) for i, p in enumerate(prompts)])
    return results

DSA patterns that show up in this role's coding rounds

You're unlikely to get a hard graph theory problem. You are likely to get something that looks like systems-with-numbers.

PatternWhy it matters hereTypical problem framing
Hash map / hash setIdempotency keys, dedupe, prefix-cache index, request-by-ID"De-dup these requests"; "implement a small LRU"
Sliding windowLatency percentiles over time, rate limiters, queue depth tracking"Compute p99 over the last N seconds"
Heap / priority queuePriority scheduling, soonest-deadline jobs, top-k"Pull the next inference job from a multi-priority queue"
DequeBounded FIFO queues, monotonic queue for max-in-window"Bounded batch buffer with timeout"
Prefix sum / countersToken counting, rolling sums, budget tracking"Total tokens served in the last minute"
Two pointersWindow over sorted streams, merge intervals"Merge overlapping reservation windows"
Greedy / bin-packingPack jobs onto GPUs, fit requests in a batch"Place these jobs onto N nodes"
Simple graphTopological ordering for pipeline stages, dependency DAG"Order these training steps"
Reservoir samplingSampling logs at fixed rate without buffering everything"Pick a uniform sample from a stream"

Big-O sanity

Senior interviewers don't ask you to recite complexities; they expect you to reach for the right structure without thinking. Refreshers worth being cold on:

StructureLookupInsertNotes
Python dict / setO(1) avgO(1) avgHash collisions in worst case; rare
Python listO(1) indexO(1) append, O(n) middlepop(0) is O(n); use deque
collections.dequeO(1) endsO(1) endsO(n) middle; great for queues
heapqO(1) minO(log n)Min-heap; negate for max
Sorted list / SortedContainersO(log n)O(log n)Convenient but third-party

For a coding round, talk out loud about the complexity of your choice before you write the code. "I'll use a heap because I need fast min and insertion is logarithmic" closes 80% of the "why this structure?" follow-up.

Code-style signals senior interviewers watch for

  • Start with the signature and the data model. A class with fields. Method signatures. Then bodies. Top-down beats bottom-up under pressure.
  • Names that read like the problem. Not i, j, x. Use request, deadline_ms, queue.
  • Edge cases first. Empty input, single-element, capacity zero, time going backward.
  • One function, one responsibility. When you start to feel the function ballooning, extract.
  • Type hints in Python. Free documentation.
  • Test as you go. A small assert at the bottom that exercises the happy path is worth more than racing to "done."
  • Explain trade-offs out loud. "I could use a sorted list here, but lookups would be log; for 100k entries that's negligible, so I'd take the simpler code."
  • Recover from mistakes calmly. If you spot a bug, say "wait, that's wrong; here's the fix." Don't try to silently rewrite.
The default opening move

When given a problem, take 60 seconds to: (1) restate it, (2) clarify one assumption, (3) name the data structure, (4) name the complexity target. Then code. The setup is what separates the senior take from the junior take.

What to rehearse this week

For this role, drill these eight kinds of problem until they're reflexive. Chapter 11 has worked examples of each:

  1. Token-bucket rate limiter.
  2. Sliding-window percentile (p95/p99) over a stream.
  3. Priority queue with multiple classes & preemption.
  4. Bounded batch buffer (merge requests up to N or time T).
  5. Bin-packing — place items of varying memory on bins of fixed capacity.
  6. Connection pool with timeout & fairness.
  7. LRU cache (and a brief discussion of how this maps to KV-cache eviction).
  8. Topological order over a small DAG (pipeline stages).

Each takes 25-35 minutes. Do them on a timer. Once you've solved each once, do them again from scratch a day later. The second pass is what builds the under-pressure version.