Full Stack Architecture and Feature Design Questions
Ability to design complete features considering frontend UX, backend API design, database schema, and data flow. Understanding of separation of concerns and communication between layers. API-first design thinking. Discussing trade-offs (e.g., complex queries on backend vs post-processing on frontend). Designing for extensibility and maintainability.
HardSystem Design
88 practiced
Design a billing decision API that must enforce strict correctness (no double-charges) while operating in a multi-region deployment with network partitions possible. Discuss where to place the canonical ledger (single region leader vs partitioned per customer), techniques to achieve serializability (leader-election, consensus groups), and how to balance latency and availability.
Sample Answer
Requirements (functional + non-functional)- Strong correctness: no double-charges (strict serializability for billing decisions).- Multi-region deployment; network partitions possible.- Reasonable latency for customers worldwide.- High availability preferred but never at the cost of correctness.Recommendation (high-level)- Shard ledger by customer (or small customer-group) and give each shard its own canonical ledger implemented as a Raft/Paxos consensus group replicated across regions. This limits contention, bounds the fault domain, and avoids a single global leader bottleneck.- Each consensus group provides a single serializing leader which accepts mutate requests. All writes are appended to the ledger with unique idempotency keys (client-provided or generated) and are replicated with quorum before acknowledgement → prevents double-charges.Why per-customer shards vs single-region leader- Single global leader simplifies correctness but is a latency and availability bottleneck and single point of failure in face of inter-region partitions.- Per-customer shards allow locality (pin the leader to a nearby region) and horizontal scale. Strong consistency is preserved within each shard by consensus.Techniques to achieve serializability- Consensus protocol (Raft/Paxos) per shard: leader serializes requests; committed via majority quorum across replicas.- Leader-election handled by protocol; when a leader is partitioned, followers will elect a new leader only when majority present — this preserves safety (no split-brain).- Idempotency tokens + deterministic conflict resolution: every billing command has a unique operation id and is applied exactly-once (append-if-not-seen).- Assign monotonic commit index (log sequence number) as the source of serialization order. For cross-shard operations (rare): use two-phase commit coordinated by a leader/coordinator or use a global ordering service (e.g., global Raft for cross-shard transactions) but keep these rare.Balancing latency and availability- Latency: place at least one replica in each region; prefer leaders in region with majority of that customer’s traffic (sticky routing). Use read-only local replicas for reads (reports) but ensure reads requiring strict serializability go to leader or use linearizable reads supported by Raft (leader lease or read-index).- Availability vs correctness: choose safety-first for billing: on partition, if a shard cannot reach a quorum, reject writes (fail closed) to avoid double charges. Consider configurable policies per customer (high-availability vs strict-safety).- Optimize perceived latency: acknowledge quickly only after quorum; use pipelining, batch commits, client-side retries with backoff and dedup token.Operational considerations- Monitoring of leader placement, quorum health, and tail latencies.- Automated draining/migration: when moving leader for locality, ensure coordinated transfer to avoid lost leader leases.- Testing: chaos testing (partitions, leader loss), idempotency verification, and reconciliation jobs (audit-only ledger reader to detect anomalies).- Compliance/audit: append-only immutable log, signed entries, and periodic reconciliation with payment processors.Trade-offs summary- Per-shard consensus: strong correctness, scalable, lower cross-region latency, slightly more operational complexity.- Global leader: simpler but high latency and single point of failure.- Availability choices: allow configurable relaxation for non-critical flows, but default to correctness-first for billing.
MediumSystem Design
51 practiced
Design an autocomplete/suggestions endpoint capable of handling 10k queries per second with <50ms P95 latency. Discuss data structures (tries, prefix indexes), caching strategies, personalization for returning users, and how to integrate sponsored/promoted suggestions without degrading relevancy.
Sample Answer
Requirements:- Functional: return top N suggestions for a typed prefix, 10k QPS, P95 <50ms.- Non-functional: high availability, personalization, sponsor insertion without hurting relevancy.High-level architecture:Client → Edge (CDN + rate limiter) → API Gateway → Frontend autoscaled stateless service → Suggestion Service (read-only) → Read store(s): in-memory caches (Redis/Memcached) + primary search index (sharded), plus user profile store and analytics for personalization.Core data structures:- Compressed trie (radix/patricia trie) held in-memory per shard for ultra-fast prefix scan and minimal memory. Stores pointers to top-K suggestion IDs per node (precomputed popularity/scoring) to avoid deep traversal.- Alternatively, prefix inverted index (term → sorted suggestion list) stored in Redis sorted sets for easy top-K retrieval and atomic score updates.Tradeoff: trie is fastest for memory-local lookups; prefix index is easier to shard and update.Caching strategy:- Multi-layer: - Edge/browser caching for identical prefixes. - L1: local per-instance LRU cache for hot prefixes. - L2: distributed cache (Redis cluster) storing top-K results per prefix; TTL short (1–10s) to reflect freshness. - Populate cache asynchronously on writes or with write-through when suggestion popularity changes.- Pre-warm cache for high-traffic prefixes using offline popularity lists.Personalization:- Lightweight reranking at request time: fetch global top-K from cache, retrieve user signals (recent queries, history, locale, device) from fast key-value store, apply a simple scoring function (weighted linear combination: recency*α + relevance*β + CTR*γ) to rerank top-K. Keep personalization compute O(K) (K small, e.g., 50) to meet latency.Sponsored/promoted suggestions:- Keep sponsored items in a separate bucket with metadata (bid, quality score).- Integrate via constrained re-ranking: after personalization/relevance ranking, merge sponsored candidates using business rules (e.g., at most M sponsored per response, minimum relevancy threshold, diversity constraints). Use auction score = bid * quality + relevanceBoost and only allow sponsored items above threshold to preserve UX.- Do insertion post-relevance to avoid displacing highly relevant organic suggestions.Scalability & latency considerations:- Shard index by prefix hash; replicate for read-scaling.- Serve reads from in-memory caches; fall back to local trie or Redis sorted sets.- Keep request path synchronous operations minimal: one cache read + one user-profile read + in-memory rerank. Target 1–3 network hops.- Use circuit-breakers and degrade gracefully (fallback to global popular suggestions).Monitoring & metrics:- Track latency P95/P99, cache hit rate, CTR, sponsored CTR, relevancy loss, error rates. A/B test sponsor placement rules.This design prioritizes fast O(1)-ish lookups via precomputed top-K per prefix, cheap per-request personalization, and controlled sponsored integration so business needs don’t harm perceived relevance.
MediumTechnical
40 practiced
Design an observability strategy for a full-stack feature: what frontend instrumentation (events, RUM), backend metrics, distributed tracing, and logging would you add to quickly detect and diagnose user-impacting regressions? Propose SLOs and alerting rules tied to user experience.
Sample Answer
Goal: detect user-impacting regressions quickly and enable fast root-cause diagnosis (where, why, who). Instrumentation must link frontend UX signals to backend traces, metrics and logs.Frontend (RUM + events)- RUM: capture page load, SPA route change, first input delay (FID), largest contentful paint (LCP), cumulative layout shift (CLS), time-to-interactive (TTI). Tag with user-id (hashed), session-id, region, browser, app version, feature-flag state.- Custom UX events: feature_click, feature_submit, feature_error with payload {component, userFlowId, inputDataHash}.- Error collection: capture JS exceptions with stack, source map mapping, breadcrumb trail (last N user events).- Performance spans: instrument long tasks, XHR/fetch timings, resource timings; propagate trace-id header.Backend metrics- High-cardinality metrics: request latency histogram (p50/p90/p99), throughput (rps), error rate (4xx, 5xx), backend processing duration, queue lengths, DB call latencies, cache hit rate. Tag by endpoint, service, feature flag.- Business metrics: success rate of the feature (e.g., checkout_complete / checkout_started).Distributed tracing- Ensure end-to-end trace propagation (W3C traceparent). Create meaningful spans: frontend (user click -> navigation), API gateway, service handlers, DB queries, external API calls, background jobs. Attach annotations: userFlowId, featureFlag, error codes, payload sizes.- Sample enough traces for errors and slow requests (100% for errors, dynamic tail sampling for high-latency).Logging- Structured logs (JSON) with trace_id, span_id, user_id (hashed), request_id, feature_flag. Log warnings/errors with stack and context. Correlate logs to traces and metrics.SLOs & Alerts (user-centric)- SLOs: - Availability SLO: 99.9% of feature-successful transactions over 30 days. - Latency SLO: p95 end-to-end time < 1.5s. - Error SLO: <0.5% user-visible errors (30d).- Alerting rules: - Page-load RUM p75/p95 degradation: alert if p95 increases >30% vs baseline for 15m. - Feature failure surge: alert if feature_error rate > 3x baseline and >0.5% absolute in 5m. - Backend error spike: service 5xx rate >1% AND corresponding traces show increased db latency. - SLO burn-rate: notify on >4x burn rate for SLO over 1h window. - High tail latency: p99 end-to-end > threshold for 10m with traces showing common slow spans.- Alerts include links: sample traces, RUM session replay or breadcrumbs, dashboards filtered by app version/region/feature flag.Runbooks & automation- For each alert include runbook steps: check recent traces, filter by feature flag, look at recent deployments, rollback if correlated, capture session replay for affected users.- Automate paging for high-severity; create slack summaries for less severe regressions.Why this works- RUM + custom events surface real user impact. Traces connect frontend-visible slowness/errors to backend spans. Metrics quantify scope and SLOs focus on user experience. Structured logs give contextual detail for debugging. Together they minimize MTTR and reduce noisy, non-actionable alerts.
MediumTechnical
57 practiced
Design a JSON Schema (draft-07 or later) for a 'notification' resource that supports polymorphism for three variants: email, push, and in-app. Include a 'type' discriminator and variant-specific required fields. Explain how you'd validate incoming request bodies and handle unknown variants gracefully.
Sample Answer
Here's a concise design and guidance.JSON Schema (draft-07 compatible) with a type discriminator using oneOf and per-variant const checks:Validation strategy and handling unknown variants:- Validate incoming request bodies using a JSON Schema validator (Ajv for Node, jsonschema for Python, everit for Java). First check the root schema: oneOf will select the matching variant based on the "type" const.- If validation passes: proceed with variant-specific processing (send email, push, or create in-app record).- If validation fails and errors show no matching oneOf branch: - Inspect the "type" field. If missing or not one of the known types, return a 400/422 with a clear error: "unsupported notification type: <value>" and include allowed types for client guidance. - If "type" is known but variant validation fails, return 400/422 with detailed validation errors (which fields are missing/invalid).- To handle schema evolution gracefully: - Accept unknown fields in a controlled way by removing additionalProperties:false or by allowing a top-level "metadata": { "type": "object", "additionalProperties": true } to store vendor-specific extensions without breaking validation. - For forward-compatibility with new variants, implement a fallback policy: if type === "experimental" or unknown and you want to accept without full validation, validate only common required fields (id, type) and persist the payload in a raw_data field, logging a warning and returning 202 Accepted for asynchronous processing.- Best practices: - Keep schema authoritative in your API contract and version it when changing required fields. - Return machine-readable error payloads (e.g., JSON: { code, message, details }) so clients can programmatically fix requests. - Add unit tests for each variant and for unknown/invalid type cases.
json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Notification",
"type": "object",
"properties": {
"id": { "type": "string" },
"type": { "type": "string" }
},
"required": ["id", "type"],
"oneOf": [
{
"title": "EmailNotification",
"properties": {
"type": { "const": "email" },
"to": { "type": "string", "format": "email" },
"subject": { "type": "string" },
"body": { "type": "string" }
},
"required": ["type", "to", "subject", "body"],
"additionalProperties": false
},
{
"title": "PushNotification",
"properties": {
"type": { "const": "push" },
"deviceToken": { "type": "string" },
"title": { "type": "string" },
"message": { "type": "string" },
"badge": { "type": "integer", "minimum": 0 }
},
"required": ["type", "deviceToken", "title", "message"],
"additionalProperties": false
},
{
"title": "InAppNotification",
"properties": {
"type": { "const": "in_app" },
"userId": { "type": "string" },
"message": { "type": "string" },
"priority": { "type": "string", "enum": ["low","normal","high"] }
},
"required": ["type", "userId", "message"],
"additionalProperties": false
}
]
}HardSystem Design
50 practiced
Design an API gateway that supports schema evolution, canary deployments, and traffic splitting by user cohort or percentage. Explain routing mechanisms (header/cookie-based routing), session affinity concerns, and how to monitor canary health and roll back automatically if SLOs degrade.
Sample Answer
Requirements:- Support schema evolution (backward/forward compatibility), canary deployments, traffic splitting by cohort or percentage, low latency, observability, safe rollback.- SLOs: error rate, latency P95/P99, user-facing correctness.High-level architecture:- API Gateway (edge) → Router & Traffic Manager → Service Mesh (Envoy/Istio) + Control Plane → Canary Controller + Schema Registry + Telemetry/Monitoring → CI/CDKey components:1. Schema Registry: store versioned API schemas (OpenAPI/JSON Schema). Enforce compatibility rules (backward/forward/none) on publish.2. Gateway + Router: performs routing decisions using header/cookie/query param or hashed user-id for percent splits. Integrates with service mesh sidecars to direct to specific service version endpoints.3. Canary Controller (control plane): programs routing weights, cohort rules, and session affinity into the gateway/mesh via APIs. Schedules gradual shifts and can pause/rollback.4. Telemetry & Alerting: collects logs, traces, metrics (latency, error rates, business KPIs) per version. Uses Prometheus + Grafana + tracing (Jaeger).5. Automation: Alert manager + automated rollback runbook invoked by Canary Controller.Routing mechanisms:- Header-based: X-Canary-Version or Feature-Flag header for targeted users/clients.- Cookie-based: set cookie for browser sessions to ensure affinity across subsequent requests.- Query-param: useful for SDKs or testing.- Hash-based percentage: consistent hashing on user-id or session-id to deterministically map ~X% to canary (avoids sudden shifts).Implement layered rules: cohort rules (explicit allowlist) first, then cookie/header, then hash-percentage fallback.Session affinity concerns:- Use sticky cookies or consistent hashing at edge to maintain affinity. If service instance scaling changes, use session store (Redis) or JWT-stamped routing info so requests go to same version logically even if physical instance differs.- For stateful flows, prefer server-side session store or design idempotent stateless APIs.Monitoring canary health and automatic rollback:- Define SLOs and success criteria (error rate increase threshold, latency delta, business metrics).- Collect per-version metrics with tags. Canary Controller evaluates sliding-window metrics (e.g., 5m, 1h) with statistical significance (compare using anomaly detection or control chart).- Roll-forward: increase weight gradually (e.g., 1%, 5%, 25%, 100%) after passing checks.- Automatic rollback: if metrics breach thresholds (e.g., error rate +2σ or >X% above baseline, latency P95 regresses >Y ms), Canary Controller immediately reduces weight to 0 and notifies on-call, creates incident, and tags problematic traces for triage.Trade-offs & considerations:- Consistency vs availability: strict session affinity and stateful sessions complicate scale/HA; prefer stateless design.- Complexity: service mesh adds visibility and fine-grained routing but increases operational overhead.- Schema enforcement: strict compatibility reduces risk but slows evolution—use feature toggles for breaking changes and migration strategies (dual-write, adaptors).Example flow:- Dev publishes v2 with compatible schema to registry → CI/CD deploys canary pods → Canary Controller sets 1% hashed traffic routing to v2 and sets cookie for cohort users → Telemetry shows stable metrics → Controller ramps to higher weights → if SLO breach detected, automated rollback to v1 and alert created.This design provides safe evolution, deterministic traffic splitting, session-aware routing, and automated, metrics-driven canary control.
Unlock Full Question Bank
Get access to hundreds of Full Stack Architecture and Feature Design interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.