Break complex problems into smaller, manageable subproblems and solution components. Demonstrate how to identify the root problem, extract core patterns, choose appropriate approaches for each subproblem, sequence work, and integrate partial solutions into a coherent whole. For technical roles this includes recognizing algorithmic patterns, scaling considerations, edge cases, and trade offs. For non technical transformation work it includes logical framing, hypothesis driven decomposition, and measurable success criteria for each subcomponent.
MediumTechnical
125 practiced
Design an observability plan for a new microservice. Decompose into metrics (latency histograms, p95/p99, error rates, throughput), logs (structured, correlation IDs), distributed tracing spans, SLOs and alerting rules, dashboards, and sampling/tracing strategy. Define measurable SLO targets and describe how you would validate them in production.
Sample Answer
Requirements & goals:- Observe correctness, performance, and user-impact for a new microservice handling HTTP requests (0.5–5k RPS).- Enable fast incident detection, root-cause, and capacity planning while controlling costs.Metrics- Request latency: capture histogram buckets (exponential) and expose p50/p90/p95/p99. Instrument at ingress and egress.- Error rates: per-endpoint 4xx/5xx counts and % of failed requests.- Throughput: requests/sec per endpoint, per instance.- Resource metrics: CPU, memory, thread pool queue length, GC pause, connection pool usage.- Business metrics: successful payments/orders per minute, user-facing feature flags.Logs- Structured JSON logs (timestamp, level, service, env, host).- Include correlation_id (from incoming request) and trace_id. Log request_id, user_id (if available), endpoint, status, latency, error stack.- Log sampling for verbose traces (see below).Distributed Tracing- Create spans for: incoming HTTP handler, auth/validation, DB calls, downstream HTTP/RPC, cache ops. Include meaningful span names and tags (endpoint, status_code, db_query, host).- Propagate trace_id and parent_id across services.SLOs & Targets (measurable)- Availability SLO: 99.9% successful requests (HTTP 2xx/3xx) per rolling 30d (error budget 0.1%).- Latency SLO: p95 < 300ms, p99 < 800ms for user-facing endpoints, measured at ingress.- Error rate SLO: <0.2% 5xx per 30d.- Business SLO: 99.5% orders processed within 2s.Alerting rules- Page (P1): Error budget burn rate > 4x for 1h OR 5xx rate > 1% sustained 5m OR p99 latency > 2s for 5m.- On-call (P2): p95 latency > 500ms for 15m OR CPU > 85% per instance for 10m.- Ops warning: Increasing error trend (20% relative increase) or queues/backpressure metrics rising.- Include runbooks linking to dashboards, recent deploys, and rollback steps.Dashboards- Overview: traffic, error rate, p50/p95/p99, error budget remaining, recent deploys.- Per-endpoint: latency distribution histogram, throughput, errors.- Infrastructure: per-host CPU/memory, container restarts, queue sizes.- Traces: top-N slow traces, traces by error type, slowest DB queries.Sampling & Tracing Strategy- Default: sample 1% of requests for full traces to control cost.- Adaptive sampling: increase to 100% for requests that error or exceed latency threshold; or sample 100% during canary windows and for key business endpoints.- Always keep trace headers for all requests so logs can be correlated.Validation in production- Canary rollout: enable full tracing and detailed metrics for canary cohort; validate SLOs for 24–72 hours before global rollout.- Run synthetic tests/healthchecks to exercise endpoints and compare metrics to baseline.- Monitor error budget burn rate and business SLOs for first 7–30 days; if burn rate exceeds threshold, pause rollout.- Postmortem and calibration: after incidents or 30d, review SLO attainment, adjust thresholds/histogram buckets and sampling rates; add instrumentation gaps discovered from traces/logs.Why this design- Histograms + p95/p99 capture distribution and tail latency. Correlated structured logs + trace ids enable fast root-cause. SLO-driven alerts reduce noise and focus on user impact while error budgeting guides release velocity. Adaptive sampling balances cost and investigability.
MediumTechnical
60 practiced
An API endpoint is experiencing increased tail latency. Provide a decomposed triage plan: collect high-level metrics (p50/p95/p99), gather traces for slow requests, inspect database slow queries, check thread/connection pools, examine GC logs and CPU load, and run targeted load and profiling. For each diagnostic step indicate what evidence would point to that layer as the root cause.
Sample Answer
Triage plan — step-by-step diagnostics and the specific evidence that implicates each layer.1) Collect high-level latency metrics (p50/p95/p99, request rate, error rate)- What to look for: p50 stable but p95/p99 rising → tail issue. Correlate spikes with request-rate, deploys, or config changes. Increased error rate or queueing time alongside tail latency suggests downstream saturation.2) Gather distributed traces for slow requests- What to look for: traces where most time is spent in a specific span (DB call, external API, serialization). High variance across traces pointing to a single downstream service or repeated retry patterns implicates that component.3) Inspect database slow queries and locks- What to look for: slow query logs showing long-running SQL matching trace timestamps, high lock wait times, increased CPU or IO on DB host, rising connection/transaction durations. Correlating slow queries to traces confirms DB root cause.4) Check thread/connection pools and queuing- What to look for: exhausted worker threads, thread pool queue length increasing, connection pool maxed out with many threads waiting. Evidence: thread dumps showing blocked threads, metrics showing >90% pool usage and request queuing time.5) Examine GC logs and CPU load- What to look for: frequent long GCs or increasing pause times affecting latency; CPU at or near 100% (system/user), high sys time or stealing on VMs. GC pauses visible in traces that show application not running during windows implicates runtime resource contention.6) Run targeted load tests and profiling- What to look for: reproducing tail latency under controlled load confirms scalability issue. CPU/memory/IO/profiler hotspots (hot methods, lock contention, allocation churn) point to code-level causes. Use A/B changes (config, pool size) to validate fixes.7) Cross-check infra: networking, external APIs, and recent changes- What to look for: increased network latency, packet loss, or third-party API slow responses in traces; recent deploys or config changes coinciding with onset.When you find matching evidence in multiple layers, prioritize the one with direct timing overlap in traces and immediate mitigation options (e.g., increase pool sizes, fix slow query, patch hot method) and validate with targeted tests.
EasyTechnical
82 practiced
Explain the difference between top-down and bottom-up decomposition in software design. Use the example of building a RESTful user-profile microservice to show the sequence of steps for each approach, the typical risks and benefits, and when you'd prefer one over the other in a team or product context (time-to-delivery, reuse, feasibility).
Sample Answer
Top-down vs bottom-up decomposition:Top-down: start from the overall system and iteratively break it into smaller components.- Steps for a RESTful user-profile microservice: 1. Define high-level requirements: API for CRUD profiles, auth, scalability, SLA. 2. Split into modules: API layer, service layer (business rules), persistence, auth, caching. 3. Design interfaces/contracts between modules (HTTP endpoints, DTOs). 4. Implement from controllers → services → repositories → DB schemas. 5. Integrate, test end-to-end, optimize.Bottom-up: build small, well-tested components first and assemble them into the system.- Steps: 1. Identify reusable primitives: user model, validation library, DB access utilities, auth middleware. 2. Implement and unit-test these components (e.g., user repository, hashing utility). 3. Compose components into services (business logic) and then expose REST endpoints. 4. Add integration and E2E tests.Benefits & risks:- Top-down: + fast alignment to product needs, easier to prioritize features and deliver MVP; − risk of overdesign, modules may be tightly coupled or low reuse if implementations aren't validated early.- Bottom-up: + high-quality reusable building blocks, fewer surprises when integrating; − may spend time on components that aren't needed, slower initial time-to-delivery and potential misalignment with product priorities.When to prefer:- Choose top-down when time-to-delivery and clear product requirements matter (tight deadlines, MVP). Good for small teams focused on a feature end-to-end.- Choose bottom-up when building platform-level services or libraries expected to be reused across teams, or when feasibility/complexity of low-level components is uncertain and must be validated first.Hybrid: often best—deliver a vertical slice (top-down) while developing critical reusable components bottom-up in parallel.
HardTechnical
119 practiced
Design an ANN (approximate nearest neighbor) system for vector search over 1B vectors of 128 dimensions with a latency target of ~1-5ms per query. Decompose the system into index selection (HNSW, IVF, LSH), quantization (PQ), sharding and routing, re-ranking step, and index update strategies. Explain trade-offs between recall, latency, and storage, and justify an approach for the given scale and latency target.
Sample Answer
Situation: We must serve approximate nearest-neighbor (ANN) queries on 1B vectors (128‑D) with 1–5ms query latency. The design below balances recall, throughput, storage, and updateability.Index selection- Hybrid: use IVF (coarse quantizer) to partition into ~100k coarse cells, combined with per-cell HNSW graphs (IVF‑HNSW). IVF reduces candidate set; HNSW gives high-quality traversal inside cells with low CPU.- Rationale: Pure HNSW on 1B is memory-heavy; IVF narrows search so per-query work meets ms targets.Quantization- Use asymmetric distance with Product Quantization (PQ) for stored vectors: PQ (e.g., 16 bytes per vector using 16×8-bit subquantizers) plus a small residual/headroom.- Keep 1–2 bytes of scalar per-vector metadata (id, coarse cell).- Store original vectors for a small sampled subset to enable re-ranking (see below).- Rationale: PQ reduces RAM/disk footprint ~8–16× vs float32 while allowing fast ADC (asymmetric distance computation).Sharding and routing- Horizontal sharding by coarse cell ranges across many machines (shard = group of coarse cells). Aim for ~1–5M vectors/shard → ~200–1000 shards. Deploy shards on ~200–500 servers depending on memory.- Use a lightweight router: map query to top‑k nearest coarse centroids (e.g., probe = 3–10), then fan-out to corresponding shards. For latency, prefer single‑hop router that returns combined candidates.- Co-locate PQ tables and per-shard HNSW; keep routing table in memory and cached.Re-ranking- Stage 1: candidate retrieval using IVF probe + per-shard HNSW over PQ distances to produce ~100–1000 candidates.- Stage 2: re-rank top N (e.g., 50–200) using higher-fidelity distances: either dequantized PQ with precomputed lookup tables (fast), or exact float32 distance if original vector is kept on SSD/SSD NVMe and warmed cache for hottest items.- Optionally apply application-specific scoring (dot-product weights, metadata filters).Index updates- Support two paths: - Fast path (streaming): append new vectors into per-shard “delta” in-memory HNSW + PQ buffer; queries check both base and delta. Periodically merge. - Batch path: offline rebuild/merge of shards (recompute coarse centroids and rebuild per-shard HNSW) during low traffic windows.- For deletions, mark tombstones in shard metadata, and purge during batch merges.Trade-offs and justification- Recall vs latency: higher probe and larger candidate sets increase recall but add latency. We choose probe=3–10 and candidate size≈500 to hit 1–5ms with ~90–95% recall for typical distributions.- Storage vs accuracy: denser PQ (more bytes) improves accuracy but costs memory; 16B PQ is a pragmatic balance. Storing full vectors for all 1B would blow RAM; instead store full vectors for hot subset or on NVMe for re-ranking.- Complexity vs operational cost: IVF‑HNSW + PQ gives strong accuracy/latency/storage trade-off and supports incremental updates better than monolithic HNSW at this scale.Operational notes- Use CPU vectorized ADC (AVX) and SIMD for PQ distance; consider GPU offload for very high QPS.- Monitor recall/latency; adapt probe and candidate counts per SLA. Automate shard rebalancing when hotspots emerge.
HardTechnical
69 practiced
A CPU-bound function accounts for 60% of CPU across your fleet. Decompose how you would investigate and optimize it: collect profiles (sampling and instrumentation), isolate hot code paths, write microbenchmarks, consider algorithmic changes, add caching or memoization, and explore parallelization. Provide an experimental plan with measurable goals and rollback safeguards for production changes.
Sample Answer
Approach overview: treat this as an evidence-driven, incremental optimization project with safety rails. Goal: reduce that function’s CPU share from 60% to <30% (or improve request latency by X% / throughput by Y%) without regressions.1) Collect profiles- Start with low-overhead statistical sampling across representative production traffic (perf/pprof/async-profiler). Collect several runs at peak and off-peak.- Complement with targeted instrumentation (flamegraphs, counters, latency histograms, allocation profiles) in a staging environment to avoid production noise.- Correlate CPU hotspots with request types, input sizes, and tenant IDs.2) Isolate hot paths- From flamegraphs identify top call stacks responsible for CPU.- Add fine-grained tracing around those methods to capture arguments and frequency.- Reproduce in a local/staging harness with captured inputs.3) Microbenchmarks- Write deterministic microbenchmarks for the hot functions (JMH for Java, pytest-bench/pytest for Python, Google Benchmark for C++).- Benchmark current baseline and add parameterized inputs matching production distributions.- Use CI to run benchmarks and track regressions over time.4) Algorithmic changes & caching- Evaluate asymptotic improvements (e.g., O(n^2) -> O(n log n)). Prototype and benchmark.- Add memoization or LRU caches where inputs repeat; measure hit rate, memory cost, and eviction behavior.- Consider incremental/online algorithms to avoid recomputing full results.5) Parallelization- Assess safe concurrency: are sub-tasks independent? If yes, use worker pools, data-parallel map, or vectorized operations.- Measure Amdahl’s Law limits: ensure contention, GC, and synchronization don’t negate gains.- Prefer async batching or SIMD/vectorized libraries before heavy threading.6) Experimental plan & rollout- Define metrics: CPU% of function, p50/p95 latency, throughput, error rate, memory usage. Set targets (e.g., CPU% drop ≥30%, p95 latency ↓20%).- Staging: run canary traffic with feature flag. Compare metrics vs baseline for at least N hours/requests.- Gradual rollout: 1% → 10% → 50% → 100% with automated monitors and automatic rollback on threshold breaches.- Safety: feature flags, toggles, and health checks. Keep old code path deployable (fall-back). Run chaos tests for resource pressure.7) Validation & follow-up- After stable rollout, run long-duration production sampling to ensure no cold-start, memory growth, or tail regressions.- Commit microbenchmarks + profiles to repo, document changes, and add alerts for regression detection.Trade-offs: prefer algorithmic fixes first (highest ROI), then caching (memory cost), then parallelism (complexity). Always measure end-to-end user impact, not just CPU numbers.
Unlock Full Question Bank
Get access to hundreds of Problem Decomposition interview questions and detailed answers.