Demonstrate clear knowledge of the backend developer position, including core responsibilities and the technology choices that commonly support them. Topics include designing application programming interfaces, service and data models, database design and query optimization, authentication and authorization strategies, scalability and performance trade offs, reliability and observability practices, security considerations, test strategies for backend code, deployment pipelines and release workflows, and familiarity with common runtime platforms and infrastructure such as Node.js, Python, Java, PostgreSQL, MongoDB, Amazon Web Services, and Microsoft Azure. Candidates should also be able to ask targeted questions about existing architecture, integration points, expected throughput and latency, operational responsibilities, and the team ownership model.
HardSystem Design
118 practiced
Design a reliable funds transfer that must debit Account A and credit Account B across two microservices: Accounts Service (debit) and Ledger Service (record). Requirements: atomicity (no double-debit), recovery from partial failures, auditing, and support for reconciliation. Compare two-phase commit (2PC), distributed locking, and the Saga pattern (orchestrated/choreographed). Recommend an approach, outline data/schema changes, and describe compensating actions for failures.
Sample Answer
**Options overview**- 2PC: strong atomicity across services but complex, blocks resources, requires XA support; poor for microservices.- Distributed locking: central lock can serialize transfers; risk of deadlocks and single point of failure.- Saga pattern: preferred for microservices—either orchestrated (a coordinator sequences steps) or choreographed (services emit events). Use idempotency and compensating transactions.**Recommendation**- Use orchestrated Saga: orchestrator coordinates debit from Accounts Service then create ledger entry in Ledger Service. If any step fails, orchestrator triggers compensating actions (credit back) with retries and escalation.**Schema/data changes**- Accounts Service: add transfer table with transfer_id, amount, status (initiated, debited, compensated), idempotency token, timestamps.- Ledger Service: entries table with transfer_id FK, status.- Both services should record operation metadata and correlation IDs for auditing.**Ensuring no double-debit**- Use idempotency keys for debit requests; Accounts Service performs debit in a transactional way marking transfer_id consumed. Enforce unique constraint on transfer_id.**Recovery & reconciliation**- Orchestrator persists state of each Saga; periodic reconcile jobs scan inconsistent transfers (e.g., debited but no ledger record) and trigger retries or compensations.**Compensating actions**- If ledger write fails after debit: orchestrator invokes Accounts Service to credit the amount back (compensate). Ensure compensation is idempotent and audited.**Additional safeguards**- Implement durable messaging for commands/events, exponential backoff, dead-letter queues, and human-in-the-loop alerts for stuck Sagas. Maintain an audit log for reconciliation and regulatory requirements.
EasyTechnical
72 practiced
Describe the differences between logs, metrics, and distributed traces. For a backend API, provide one concrete example of what you would capture as a log entry, one as a metric, and one as a trace span. Explain how these three observability signals complement each other during incident investigation.
Sample Answer
**Definitions & roles**- Logs: structured records of events (high cardinality, rich context).- Metrics: numeric aggregated measurements over time (low cardinality, for alerting).- Traces: distributed spans showing request flow and timing across services.**Examples for a backend API**- Log entry: {timestamp, request_id, user_id, path: "/charge", status: 502, error: "upstream timeout", stack}- Metric: counter "payments.success_total" and latency histogram "payments.duration_ms" with tags service=payments,status=200- Trace span: HTTP span for /charge request with child spans for DB query and payment gateway call, including durations and service names.**How they complement each other**- Metrics alert you (e.g., spike in 502s). Traces let you pinpoint slow or failing spans and see timing across services. Logs provide detailed context and error messages for debugging specific requests once you know request_id from trace.- Combined workflow: metric alert → open representative trace(s) → inspect logs for root cause and user context.
HardTechnical
82 practiced
Describe and sketch an implementation for a strongly consistent distributed token-bucket rate limiter used across N stateless API servers. The solution must avoid race conditions and provide low-latency checks. Compare a central Redis-based approach (with Lua scripts), a Redis cluster with sharded keys, and a decentralized/gossip-based approach. Discuss availability and latency trade-offs and how to handle Redis failover safely.
Sample Answer
**Goal**: strongly consistent, low-latency token-bucket across N stateless servers.**Central Redis with Lua script (recommended)**- Single Redis (or HA pair) stores token state per key. Use an atomic Lua script to calculate tokens, refill, and consume in one command. Returns success and remaining tokens. Guarantees strong consistency and low latency if Redis is close.- Pros: Simplicity, strong correctness, low latency. Cons: Redis is a central dependency; failover must be handled carefully (use Redis Sentinel/Cluster with controlled failover and short client timeouts).**Redis cluster with sharded keys**- Shard token keys across a cluster. Use same Lua script per shard. Improves throughput and availability but adds complexity: cross-shard coordination avoided by choosing shard key wisely. Failover within cluster ok but re-sharding changes key ownership.**Decentralized/gossip-based approach**- Local token buckets with periodic reconciliation via gossip or CRDT-like approaches. Lower availability dependency but weaker consistency (risk of temporary over-issue). Useful when availability and partition tolerance prioritized over strict global limits.**Trade-offs**- Consistency vs availability: central Redis gives strong consistency; decentralized gives better availability under partition but allows small bursts.- Latency: local caches fastest; central Redis adds network hop but still low (ms) if colocated.**Handling Redis failover safely**- Use Redis Cluster with replicas and synchronous persistence tuned. During failover, clients should apply exponential backoff and short timeouts; ensure Lua scripts are idempotent; use token leases or persistent tokens so state isn't lost. For critical paths, fallback to degraded local enforcement with conservative limits until Redis recovers.
MediumSystem Design
61 practiced
Design a background processing system for image-processing tasks with the following requirements: reliable delivery (at-least-once), retry with exponential backoff and jitter, dead-letter handling for poison messages, idempotent workers, prioritized queues, and autoscaling workers. Choose between SQS, RabbitMQ, and Kafka and justify your choice. Sketch worker lifecycle, how to handle retries and DLQs, and how to monitor backlog and processing latency.
Sample Answer
**Queue choice**- For image-processing with prioritized queues, retries, DLQs and autoscaling: choose SQS (or Amazon SQS with FIFO where ordering matters) or RabbitMQ; Kafka is durable/high-throughput but complex for DLQ semantics and at-least-once idempotency. I recommend SQS + Lambda/ECS workers for managed retries and DLQ features.**Worker lifecycle**- Poll message, claim/visibility timeout, process idempotently (use message deduplication or idempotency keys in DB), on success delete message, on failure allow retry with exponential backoff + jitter by changing visibility or requeueing. After max attempts move to DLQ.**Retries & DLQ**- Implement exponential backoff with jitter (base * 2^attempt +- jitter). Configure visibility timeout > estimated processing time. Use separate DLQ per queue and monitor DLQ counts.**Idempotency**- Workers store processed-image-id or request-id in a dedupe store (Redis or DB) with TTL to detect repeats. Ensure worker operations are idempotent (overwrite, compare-and-set).**Prioritization & autoscaling**- Use multiple queues (high/normal/low priority) and scale worker pools independently based on backlog metrics. Use CloudWatch/Prometheus to autoscale based on ApproximateNumberOfMessagesVisible and processing latency.**Monitoring**- Track backlog, processing latency, failure rates, DLQ growth, retry counts. Alert on increasing DLQ or elevated latency.SQS simplifies DLQ, visibility timeout, and scaling; RabbitMQ offers richer routing and priority but requires more operational effort. Kafka suits massive throughput but requires custom retry/DLQ patterns.
EasyTechnical
64 practiced
As a backend developer, explain the primary responsibilities you would own on a typical product team. Describe how you decide between Node.js, Python, and Java when implementing a new service, referencing factors such as: latency and throughput requirements, concurrency model, library/ecosystem maturity, team familiarity, deployment targets (serverless vs containers), operational cost, and long-term maintainability. Provide three concrete decision criteria and give one example choice for a public-facing low-latency payments API and why you made that choice.
Sample Answer
**Primary responsibilities**- Ship backend features: design APIs, implement services, ensure data integrity.- Reliability & performance: monitoring, scaling, SLAs.- Security & compliance: auth, data protection.- Collaboration: work with product, frontend, infra; code reviews; mentoring.**Choosing Node.js vs Python vs Java — decision factors**1) Latency/throughput & concurrency model: choose event-driven Node.js for IO-bound, Java for high-throughput multi-threaded workloads.2) Ecosystem maturity: Python for ML/data tasks; Java for enterprise-grade libraries; Node for rich npm ecosystem.3) Team familiarity & operational cost: prefer languages the team knows for faster delivery and maintainability.**Three concrete decision criteria**- Latency requirement: low-latency (~ms) favors languages with mature async I/O and low GC pauses (Java tuned or Node with native async). - Concurrency pattern: CPU-bound tasks favor Java (threads, JNI); IO-bound favor Node/Python async.- Deployment target: serverless cold-start concerns favor lightweight runtimes (Node/Python) unless using provisioned concurrency.**Example choice**- Public-facing low-latency payments API: choose Java (Spring Boot, tuned JVM). Reason: predictable low-latency under load, strong libraries for crypto, enterprise-grade observability, mature threading/connection-pool control and GC tuning for SLAs.
Unlock Full Question Bank
Get access to hundreds of Backend Developer Role interview questions and detailed answers.