Sitemap
Engineering Under Pressure

We write about building systems that survive the real world. Backend architecture, AI engineering, DevOps, cloud, system design, performance, debugging, and production failures no theory for theory’s sake, just engineering lessons earned the hard way.

Microservices Interview Questions: 50 Senior & Staff-Level Production Scenarios

Microservices look clean on architecture diagrams because architecture diagrams do not show the 3 AM retry storm.

Most microservices interview answers begin in roughly the same place. Services are independently deployable, each owns its data, communication happens through APIs or events, Kafka handles asynchronous workflows, and Kubernetes provides deployment and scaling. Draw enough boxes around those concepts and almost any architecture can look respectable for twenty minutes.

Production is less cooperative.

The payment service times out after charging the customer. The order service retries and charges them again. Kafka delivers an event twice. Inventory commits but the following event never reaches the broker. One service takes six seconds to respond, so four upstream services accumulate thousands of waiting requests. Kubernetes sees rising latency, adds more replicas, and those replicas open enough database connections to finish destroying PostgreSQL.

Nothing in that failure requires an exotic technology. The difficult part is understanding how ordinary components interact once partial failure, concurrency, retries, and real traffic arrive.

These are 50 microservices scenarios I would prepare for in a senior or staff backend interview.

1. When should you split a monolith into microservices?

I would split when there is a meaningful boundary that benefits from independent ownership, scaling, deployment, reliability, or evolution enough to justify distributed-system complexity.

Service count is not an architecture maturity metric. A well-structured monolith can be considerably easier to operate than twenty services whose boundaries were invented before the domain was understood.

2. How would you choose microservice boundaries?

I would begin with business capabilities, ownership, data relationships, transaction boundaries, change patterns, and operational requirements.

A useful boundary should reduce coupling rather than move coupling from method calls into synchronous HTTP calls. If two services must deploy together, query each other’s databases, and call each other for every request, the separation deserves another look.

3. Should every microservice have its own database?

Independent data ownership is useful because it prevents services from coupling through shared persistence internals. That does not mean an organization must literally purchase a separate physical database server for every service.

The important boundary is ownership. Other services should generally interact through the owning service’s contract rather than treating its tables as public APIs.

4. Why is a shared database between microservices dangerous?

Services can become coupled through schemas, joins, migrations, locks, and undocumented table assumptions. One team’s schema change can silently break another service.

A shared database can still be a pragmatic transitional architecture, but it weakens independence. The trade-off should be acknowledged rather than hidden behind separate application repositories.

5. Service A needs data owned by Service B. Should A query B’s database directly?

Usually I would prefer B to expose the data through an API, event, replicated read model, or another explicit contract.

Direct database access bypasses ownership and couples A to B’s storage schema. It can feel faster initially because it removes an API call, but the long-term dependency becomes harder to evolve safely.

6. Service A calls B, B calls C, and C calls D. What concerns you?

Latency and availability compose across the chain. Every synchronous hop adds another network operation and another dependency that can delay or fail the original request.

Deep synchronous chains also make failures propagate backward. A slowdown in D can eventually consume resources in C, B, and A even though those services themselves remain healthy.

7. How would you set timeouts across that chain?

I would work from the request’s overall latency budget and allocate bounded time to downstream operations while leaving room for local processing and response delivery.

A downstream timeout longer than the caller’s remaining deadline is usually wasted work. Deadlines should ideally propagate so deeper services understand how much useful time remains.

8. Why is “retry three times” a dangerous default?

Three retries can turn one request into four attempts. When several service layers independently apply the same policy, traffic amplification can become enormous.

Retries need a reason, a bounded budget, backoff, jitter, and an understanding of whether the operation is safe to repeat. The system should also decide which layer owns the retry.

9. When is a request safe to retry?

When repeating it cannot create an incorrect additional side effect, either because the operation is naturally idempotent or because the system provides an idempotency mechanism.

A timeout does not tell the caller whether the server completed the operation. This ambiguity is particularly important for payments, orders, reservations, and other state-changing workflows.

10. How would you implement idempotency across several service replicas?

I would use a durable idempotency key associated with the logical operation and enforce atomic uniqueness or state transitions in shared authoritative storage.

An in-memory map cannot coordinate independent replicas and disappears during restart. Idempotency needs to survive both concurrency and process failure.

11. Two requests with the same idempotency key arrive simultaneously. What happens?

Both can check for the key before either stores it if the implementation uses a naive read-then-write sequence.

The system needs an atomic claim, unique constraint, conditional write, or equivalent concurrency mechanism. Idempotency is partly a distributed concurrency problem.

12. Should an idempotency key return the original response?

Often that provides useful semantics because repeated delivery represents the same logical operation. The system can store enough result information to return the existing outcome.

Retention and payload size still need consideration. Idempotency records cannot necessarily live forever at unlimited scale.

13. The payment provider times out. Should you mark the payment as failed?

Not immediately, because the provider may have successfully processed the charge while the response was lost.

I would model an uncertain or pending state and reconcile using the provider’s idempotency or status APIs. Distributed systems frequently contain outcomes that are temporarily unknown rather than simply successful or failed.

14. What is the dual-write problem?

The application needs to update two independent systems, such as committing a database transaction and publishing an event. One operation can succeed while the other fails.

Without coordination, the database can contain state that downstream consumers never hear about, or an event can describe a change that never committed.

15. How does transactional outbox help?

The service writes both its business change and an outbox record within the same local database transaction. A separate process publishes pending outbox entries to the message broker.

This removes the gap between local state and durable intent to publish. It does not eliminate duplicate delivery, so consumers still need appropriate idempotency.

16. The outbox publisher sends an event and crashes before marking it published. What happens?

The event can be sent again when the publisher resumes.

That is expected in an at-least-once design. Downstream consumers should treat event IDs or business operations in a way that makes repeated delivery safe.

17. Can Kafka guarantee exactly-once business processing?

Kafka provides mechanisms that can support exactly-once behavior within specific Kafka processing boundaries, but the guarantee does not magically include arbitrary external side effects.

If a consumer updates PostgreSQL and sends an email, those operations exist outside a purely Kafka transaction. End-to-end business semantics still need explicit design.

18. How do you make a Kafka consumer idempotent?

I might persist processed event IDs, enforce a unique business key, use conditional state transitions, or rely on naturally idempotent operations.

The best mechanism is often a database invariant rather than a separate deduplication cache. Correctness should live as close as possible to the authoritative state.

19. Should every microservice publish events for every database change?

No. Events are contracts and create dependencies just like APIs.

I would publish events representing meaningful domain facts that other components legitimately need. Turning every table mutation into a public event stream can expose persistence internals and make future schema evolution painful.

20. What is event choreography?

Services react to events and publish additional events without one central component explicitly controlling every workflow step.

This can reduce direct coupling, but long workflows can become difficult to understand when business logic is distributed across many event handlers. Observability becomes critical because no single code path describes the whole process.

21. What is orchestration?

A coordinator explicitly manages workflow progression, telling participants which actions to perform and tracking state.

This can make complex business processes easier to observe and reason about, though the orchestrator itself becomes important infrastructure. The choice depends on workflow complexity rather than a rule that choreography is more “microservice-like.”

22. What is a saga?

A saga represents a distributed business workflow as a sequence of local transactions. When later steps fail, the system uses compensation or other workflow transitions rather than one global database rollback.

The difficult part is defining what compensation means. Some business actions cannot literally be undone, so the compensation may be a new business action.

23. A hotel was booked but the flight booking failed. What should the saga do?

If the product requires both to succeed together, the workflow might attempt to cancel the hotel reservation or move into a state requiring manual resolution.

The exact compensation depends on external-provider guarantees and business rules. Distributed rollback is usually domain logic rather than database rollback.

24. What happens if compensation fails?

The workflow needs retries, durable state, observability, and eventually an escalation path if automated recovery cannot succeed.

This is where simplistic saga diagrams become production systems. A compensating operation is itself a distributed operation capable of failing.

25. When would you use synchronous HTTP instead of messaging?

When the caller genuinely needs an immediate response to continue and the latency and availability coupling are acceptable.

Using Kafka for every interaction can make simple request-response workflows unnecessarily complicated. Architecture should follow communication semantics rather than technology preference.

26. When would you prefer messaging?

When work can be processed asynchronously, producers and consumers benefit from temporal decoupling, bursts need buffering, or several consumers need to react independently to an event.

Get SYSTEM DESIGN & Java Spring Boot | ProdRescue’s stories in your inbox

Join Medium for free to get updates from this writer.

Messaging also introduces backlog, duplicate delivery, ordering, schema evolution, retry, and operational concerns. The benefit needs to justify those costs.

27. Kafka lag keeps increasing. What does that tell you?

Consumers are not keeping pace with producers over the observed period, but it does not tell me why.

I would inspect partition distribution, processing latency, downstream dependencies, database capacity, retry behavior, rebalances, consumer errors, and producer rate. Lag is a symptom with many possible causes.

28. Would you automatically add consumers?

No. Additional consumers help only when partitions allow more parallelism and downstream capacity can absorb the increased concurrency.

If PostgreSQL is already saturated, doubling consumers can double database pressure while making message-processing latency worse.

29. What is a poison message?

A message that repeatedly fails processing because of malformed data, incompatible assumptions, a deterministic application bug, or another persistent condition.

Retrying it indefinitely can block progress or waste resources. After bounded attempts, it often needs isolation and an explicit remediation workflow.

30. Is a dead-letter queue enough?

No. A dead-letter queue prevents certain failures from blocking the main processing path, but somebody still needs to know why messages arrive there and how they are recovered.

A DLQ without monitoring and replay procedures is a graveyard, not an incident strategy.

31. How do you evolve event schemas without breaking consumers?

I prefer additive, backward-compatible changes when possible and avoid assuming every consumer upgrades simultaneously.

Schema governance, versioning, compatibility testing, and clear ownership become increasingly important as consumer count grows. An event published by one team can become infrastructure for twenty others.

32. How would you version an HTTP API between microservices?

I first try to evolve contracts compatibly by adding optional fields and preserving existing semantics. Explicit versions become useful when incompatible behavior genuinely needs to coexist.

Versioning does not remove migration work. The organization still needs to know when old contracts can be retired and which callers remain.

33. Why is backward compatibility critical during deployments?

Different versions of services often run simultaneously during rolling deployments. Producers and consumers may therefore upgrade at different times.

A release that requires every service to switch at the same second recreates distributed deployment coupling. Compatibility creates room for independent evolution.

34. How would you perform a breaking database migration safely?

I would usually separate it into compatible stages. Add the new schema first, deploy applications that understand both old and new states, migrate data as needed, move traffic or writes, and remove the obsolete structure later.

The exact sequence varies, but the principle is avoiding a moment where old and new application versions require mutually incompatible schemas.

35. Why can service discovery fail even when every service is running?

Instances may be registered incorrectly, DNS can be stale or unavailable, health state may be wrong, networking rules can block communication, or callers may retain outdated endpoints.

A process being alive does not prove that another service can discover and reach it. Distributed availability includes the path between processes.

36. Should a service restart when one downstream dependency is unavailable?

Usually not merely because a dependency is temporarily unavailable. Restarting the caller does not repair the downstream service and can create additional startup traffic.

The caller should generally handle dependency failure through bounded waiting, degradation, or failure responses while its own process remains healthy.

37. What is a circuit breaker protecting?

Primarily the caller’s resources and the failing dependency from repeated requests that are unlikely to succeed.

It helps the caller fail quickly during a known bad period. The service still needs a meaningful behavior while the circuit is open.

38. What is a retry storm?

Many requests fail and are retried, increasing traffic against a dependency that is already struggling. The extra traffic causes more failures, which creates more retries.

Several service layers retrying simultaneously can amplify the effect dramatically. Backoff, jitter, retry budgets, and clear ownership help break the loop.

39. What is a cascading failure?

A problem in one component causes resource pressure or failures in dependent components, which then affect their own callers.

For example, a slow database exhausts one service’s connection pool. Requests accumulate, upstream calls time out, clients retry, and traffic increases until services that were initially healthy also lose capacity.

40. How do you limit the blast radius of a failing dependency?

Timeouts, concurrency limits, bulkheads, circuit breakers, load shedding, queue boundaries, and degraded modes can isolate different types of failure.

The correct mechanism depends on how the dependency consumes caller resources. Failure isolation should be designed around actual resource paths.

41. One customer generates half of all traffic. What do you do?

I would identify which resources that tenant consumes and whether per-tenant limits or isolation are necessary.

Multi-tenant services should not assume customers are equally sized. A single large tenant can consume shared thread pools, database capacity, Kafka partitions, caches, or external quotas and degrade everyone else.

42. How would you implement per-tenant isolation?

Depending on the workload, I might use rate limits, concurrency limits, separate queues, partitioning, dedicated resources for very large tenants, or fair scheduling.

Complete physical isolation is expensive, so the design should isolate the resources that create the actual noisy-neighbor risk.

43. What should happen when a microservice becomes overloaded?

The worst option is usually accepting unlimited work until resources collapse.

The service needs bounded concurrency or queues and should reject, defer, or degrade excess work once safe capacity is reached. Fast failure can protect overall availability better than slow universal failure.

44. Why can Kubernetes autoscaling make a microservice incident worse?

New replicas create additional concurrency. They may open more database connections, start more Kafka consumers, warm caches, and send more requests to dependencies.

If the bottleneck is downstream, scaling the caller can increase pressure rather than relieve it. Autoscaling needs system-level capacity awareness.

45. How would you trace one business transaction across ten services?

I would propagate distributed trace context across synchronous and asynchronous boundaries and include useful business identifiers where appropriate.

A trace can show technical execution, while business identifiers help operators follow workflows that span minutes or hours. Observability needs to survive asynchronous boundaries.

46. Is distributed tracing enough?

No. Traces are one part of observability alongside metrics, logs, events, profiles, and business-level signals.

Sampling can also mean the exact problematic request is not always available. Good systems allow engineers to correlate several evidence sources rather than depending on one tool.

47. How do you know whether a microservice is healthy?

I care about whether it can perform its intended business role within expected latency and correctness boundaries.

A green health endpoint proves very little if Kafka processing is six hours behind or every payment ends in a manual reconciliation queue. Process health and business health are different layers.

48. When would you merge two microservices back together?

When the separation creates more coupling and operational cost than independence. If the services always deploy together, share the same ownership, require synchronous communication for most operations, and cannot evolve independently, the boundary may not be useful.

Architecture is allowed to move backward toward simplicity. Service consolidation can be an improvement rather than a failure.

49. What is the biggest mistake teams make when adopting microservices?

They distribute the code before understanding the domain and operational consequences.

The result can be a distributed monolith where every feature crosses several services, deployments require coordination, and failures travel through long synchronous chains. The organization pays microservice costs without receiving much independence.

50. What separates a senior microservices answer from a staff-level answer?

A senior engineer can design service boundaries, communication, persistence, consistency, resilience, and observability while reasoning about production failure. A staff engineer additionally considers how those choices affect teams, migrations, ownership, platform cost, incident response, and architecture evolution over several years.

The staff-level question becomes less about whether microservices can solve the problem and more about whether the organization should pay the permanent operational cost of that solution.

Microservices Do Not Remove Coupling. They Make You Choose Where It Lives.

One reason microservices initially feel clean is that code ownership becomes visible. Instead of one enormous application, teams see separate repositories, databases, deployment pipelines, and APIs. The boundaries are easier to draw, and independent deployments can genuinely accelerate organizations when those boundaries align with the business.

The uncomfortable part arrives later. A method call that previously took microseconds becomes an HTTP request that can time out after the remote service already completed the operation. One database transaction becomes several local transactions connected by events. A function call that happened exactly once becomes a message that may arrive twice. A local refactoring becomes an API migration involving several teams.

The complexity did not appear because microservices are bad. It appeared because moving computation across failure boundaries changes the engineering problem.

That is why I become suspicious when an interview answer reaches for another service too quickly. Every service should buy something meaningful: independent scaling, ownership, deployment, failure isolation, security, data boundaries, or organizational autonomy. If it buys none of those, the team may simply be converting cheap in-process coupling into expensive network coupling.

The strongest microservices architecture is therefore not necessarily the one with the largest number of services. It is the one where the team can explain why each important boundary exists, what happens when communication across that boundary fails, and how the system returns to a correct state afterward.

That is also the difference between drawing microservices and operating them.

Go Deeper

If you’re preparing for senior or staff backend interviews and want deeper follow-ups around microservices, distributed transactions, Kafka, databases, caching, consistency, scaling, and failure recovery, the Senior System Design Interview Playbook: Follow-Ups, Trade-Offs & Architecture Patterns is here:

For broader senior and staff interview preparation across system design, coding, architecture, production reasoning, and behavioral rounds:

I also publish deeper notes on microservices, distributed systems, Java, backend architecture, system design, and production failures here:

--

--

Written by SYSTEM DESIGN & Java Spring Boot | ProdRescue

Turn backend skills into real products. Build, launch, and scale profitable SaaS.

Published in Engineering Under Pressure

We write about building systems that survive the real world. Backend architecture, AI engineering, DevOps, cloud, system design, performance, debugging, and production failures no theory for theory’s sake, just engineering lessons earned the hard way.