Problem statement
Design the class model and public API for a resilient HTTP-style API client: the object graph a service uses to call a remote dependency and survive its transient failures without hammering it or corrupting shared state. This is the client kernel that application code calls; the actual socket/transport is a seam you depend on, not something you build here.
Operating context. One client instance is shared across many worker threads in a single process, wrapping calls to an unreliable downstream (a payments or inventory dependency that occasionally times out, returns 503, or drops the connection). Each call must apply a per-attempt timeout, decide whether a failed attempt is worth retrying, wait a computed delay, and stop once a retry budget or deadline is reached. The retry decision differs by outcome: a network timeout or 503 is usually retriable, a 400 or 404 is fatal, and whether to retry at all depends on whether the request is safe to repeat. Backoff must grow between attempts and be randomized so a fleet of clients does not resynchronize into a thundering herd. The client is on a hot path, so time must be injectable — tests cannot sleep in real seconds.
Out of scope. The actual socket/TLS/HTTP wire implementation (assume an injected transport with a send-one-request method), connection pooling and keep-alive, request/response body serialization, service discovery and load balancing, a full circuit breaker (you may leave a seam for one), and distributed tracing.
What to produce. The class hierarchy (the client facade, a pluggable RetryPolicy, a Backoff strategy, a failure Classifier, a Clock/Sleeper abstraction, and the value objects for a request, a response, and an attempt outcome), the public API each exposes, and the state transitions of a single call across its attempts (attempt -> classify -> decide retry -> backoff+sleep -> re-attempt, until success, exhaustion, or a fatal outcome). Be explicit about: how the retry policy is swapped without editing the client, how exponential backoff with jitter is computed and bounded, how idempotency/safety gates whether a retry is even allowed, how retriable-versus-fatal classification is pluggable, and how injecting the clock makes the whole thing deterministically testable.
Requirements
This assessment is a Premium feature.
The statement above is free to read. The functional and non-functional requirements, and the graded canvas that scores your design against them, come with Premium.
Topics
- System Design LLD
- Patterns Strategy
- Oop Solid
- Testability Clock
- Concurrency Threadpool