Skip to main content

Rust engineer system design interview questions

10 questions on system design for rust engineer candidates. Expect prompts such as “Design a high-throughput REST API service in Rust” and “Design a gRPC microservice in Rust with tonic”, each with a worked answer outline and the follow-ups interviewers push on.

Questions

Showing 1 to 10 of 10 system design questions.

As asked

Design a Rust HTTP service that handles 50,000 requests per second for a read-heavy endpoint backed by Postgres. Cover the framework choice, connection pooling, caching, observability, and how you would handle hot spots.

Sample answer outline

Framework: axum on tokio for async handling. Connection pool: deadpool-postgres or sqlx PgPool sized to saturate Postgres without overloading it (typically 10 to 20 connections per Postgres core). Layer a Redis cache in front with read-through and a short TTL for hot rows. Observability: tracing + OpenTelemetry exporting to Jaeger or Datadog, Prometheus metrics via axum middleware. Hot spots: shard reads to read replicas, add a local in-process cache (moka) for the hottest keys to avoid Redis roundtrips.

Expect these follow-ups

  • How would you handle cache invalidation when the underlying Postgres row changes?
  • At what point does the Tokio thread pool stop scaling and what do you do then?
system-designaxumtokiopostgrescaching

As asked

You need to expose an internal gRPC API for a Rust microservice that receives streaming telemetry from IoT devices. Describe the tonic setup, proto-buf schema choices, streaming patterns, backpressure, and failure handling.

Sample answer outline

Use tonic with prost for protobuf. Schema: define service with server-streaming or bidirectional streaming for telemetry ingestion. Backpressure: tonic streaming uses tokio channels under the hood; tune buffer size to signal slow consumers. Failure handling: tonic maps errors to gRPC status codes, implement retry at the client with exponential backoff and deadline propagation. Add interceptors for auth (JWT validation) and tracing header propagation.

Expect these follow-ups

  • How do you add TLS to a tonic server?
  • What protobuf field options help with forward compatibility?
system-designgrpctonicprotobufstreaming

As asked

You are building a CLI tool for developers that reads large log files, filters and transforms lines, and outputs structured JSON. Describe the design: argument parsing, I/O pipeline, error handling, testability, and distribution strategy.

Sample answer outline

Argument parsing with clap derive macros. I/O pipeline: BufReader for streaming reads to avoid loading the full file into memory, process line by line, serialize with serde_json. Error handling: use anyhow for the binary, exit non-zero with a user-friendly message on any error. Testability: unit test transformation logic against in-memory slices, integration test against temp files. Distribution: cross-compile for Linux/macOS/Windows using cargo-cross, publish binaries via GitHub Releases plus a Homebrew formula.

Expect these follow-ups

  • How would you add progress reporting for large files without blocking output?
  • What does cargo-dist automate for binary distribution?
system-designcliclapiodistribution

As asked

Design a Rust WebSocket server that fans out events to thousands of connected clients. Cover connection management, the broadcast mechanism, reconnection, and how you would handle slow consumers without blocking fast ones.

Sample answer outline

Use tokio_tungstenite or axum's WebSocket support. For broadcast, maintain a tokio::sync::broadcast::Sender; each connected client task subscribes a Receiver. Slow consumer: broadcast channel has a lagged semtanics; when a receiver falls behind capacity, it receives a RecvError::Lagged and can decide to disconnect or skip. Reconnection: clients should implement exponential backoff with jitter. Connection registry: DashMap from connection ID to a oneshot or abort handle for targeted disconnection.

Expect these follow-ups

  • How do you authenticate a WebSocket upgrade request before establishing the connection?
  • What is the backpressure story when a client's TCP buffer fills up?
system-designwebsockettokiobroadcastreal-time

As asked

A Rust service reads from Kafka, calls an HTTP dependency, and writes results to Postgres. How would you design backpressure so it fails predictably under load?

Sample answer outline

A good design bounds every queue and makes overload visible before memory grows without limit. Kafka polling should be tied to downstream capacity, with pause and resume or controlled commit lag rather than unbounded task spawning. HTTP concurrency should be capped with a semaphore and short deadlines, while Postgres writes should use bounded batches and connection pool limits. The service should expose lag, queue depth, retry counts and dropped or dead-lettered messages. Candidates often miss cancellation and shutdown semantics, especially making sure in-flight work is either committed or replayable.

Expect these follow-ups

  • Where do you commit offsets in this pipeline?
  • How do you distinguish a slow dependency from a poison message?
  • What metrics would page you before users notice?
tokiobackpressurestreaming

As asked

Design a Rust Kafka consumer using rdkafka that processes messages at-least-once with manual offset commits, handles poison-pill messages gracefully, and can scale horizontally. What happens to in-flight messages during a rolling restart?

Sample answer outline

Use StreamConsumer from rdkafka in async mode. Manual commit after successful processing to guarantee at-least-once. Poison-pill handling: wrap processing in a Result, on repeated error send message to a dead-letter topic and commit the offset to unblock the partition. Horizontal scaling: one process per Kafka consumer group partition; Kafka rebalances on group membership change. On rolling restart, in-flight messages after last commit are reprocessed because the consumer shutdown without committing them.

Expect these follow-ups

  • How would you achieve exactly-once semantics using Kafka transactions from Rust?
  • What is the max.poll.interval.ms and how does processing time affect rebalancing?
system-designkafkardkafkamessagingreliability

As asked

You need to parse a custom binary protocol with a fixed header, variable-length payload, and optional TLV extension fields. Describe how you structure the parser, handle partial reads from a TCP stream, and ensure zero-copy where possible.

Sample answer outline

Use nom or winnow for combinator parsing against a byte slice. For partial reads from a TCP stream, maintain a BytesMut ring buffer, attempt parse, and on Incomplete return, await more data before retrying. Zero-copy: parse borrows slices directly from the BytesMut buffer until a copy is needed (e.g., when storing the payload). Define the header as a #[repr(C)] struct with byteorder-correct reads rather than raw transmute for safety.

Expect these follow-ups

  • How do you test a parser against arbitrary byte sequences for correctness?
  • What does nom's Incomplete combinator return and how does it interact with streaming?
system-designparsingnombinary-protocolzero-copy

As asked

Design a Rust library that enforces per-user rate limits using a sliding window algorithm, backed by Redis. The library will be used across multiple service instances. Describe the data structures, Redis commands, and how you handle Redis unavailability.

Sample answer outline

Sliding window: store per-user sorted set in Redis with timestamp as score. ZADD + ZREMRANGEBYSCORE + ZCARD in a MULTI/EXEC transaction per request. Atomic via Lua script to avoid TOCTOU. Connection pool via deadpool-redis. Redis unavailability: fail-open (allow request but log) or fail-closed with a circuit breaker (governor or custom). Expose a trait interface so callers can swap to in-memory for tests.

Expect these follow-ups

  • How does a token bucket differ from a sliding window and when would you prefer it?
  • What is the worst-case Redis latency contribution to your p99 response time?
system-designrate-limitingredisconcurrencydistributed

As asked

You need to write Rust firmware for a Cortex-M4 with 128 KB flash and 32 KB RAM, no OS. Describe how you structure the project with no_std, how you handle I/O without an allocator, and how you test the business logic off-target.

Sample answer outline

Use #![no_std] #![no_main] with cortex-m and embedded-hal HALs. Avoid heap: use heapless for fixed-size collections or static allocation. Drivers are generic over embedded-hal traits so they are testable on any platform. Off-target testing: the business logic crate uses no_std but can run on std test builds using mock implementations of embedded-hal traits. Use probe-rs or cargo-embed for on-target flashing and RTT logging.

Expect these follow-ups

  • How do you handle interrupts safely in Rust without a kernel?
  • What does RTIC provide over bare-metal interrupt handlers?
embeddedno-stdcortex-membedded-halfirmware

As asked

Your Rust workspace has 40 crates and CI takes 12 minutes. Design a remote build caching system that caches compiled artifacts by input hash, is safe to use from multiple parallel CI workers, and integrates with cargo.

Sample answer outline

sccache is the reference implementation: it wraps the compiler, hashes inputs (source, flags, env), and stores outputs in S3 or GCS. Alternative: cargo's -C remap-path-prefix for reproducible hashes. Worker safety: S3 is safe for concurrent writes to different keys. Incremental linking: link codegen units per crate, cache only changed crates. Measure hit rate and cache size separately. GitHub Actions caching: use actions/cache with Cargo.lock hash as key prefix.

Expect these follow-ups

  • Why does sccache not cache proc-macro crates and what are the workarounds?
  • How does cargo's own incremental compilation differ from artifact caching?
system-designbuildcargocachingci