System Design Interview Questions: Microservices Architecture

Reviewed by Mark Dickie · Last updated

Microservices architecture is a design approach where a single application is split into small, independently deployable services, each responsible for one bounded business capability. For a system design interview focused on microservices, you need to understand how services communicate (synchronous REST/gRPC vs. asynchronous messaging), how you handle data consistency without a shared database, and how you reason about failure in a distributed system. Interviewers want to see that you can name concrete trade-offs rather than just describe the style in general terms. Knowing when microservices are the wrong call matters as much as knowing how to build them well.

What does a microservices system design interview actually test?

Interviewers are checking three things at once: your ability to decompose a domain into coherent services, your knowledge of the operational patterns that keep those services running in production, and your judgment about where the costs outweigh the benefits. Questions range from "split a monolith" exercises at the easier end to deep trade-off discussions about consistency models and failure-mode cascades at the harder end.

Core concepts to have solid before the interview

The table below maps the key topic areas to the specific things you should be ready to explain or draw on a whiteboard.

Topic areaWhat you must be able to explain
Service decompositionDomain-driven design boundaries, single responsibility per service
Inter-service communicationREST vs. gRPC vs. message queues; when to choose each
Data managementDatabase-per-service pattern, eventual consistency, the Saga pattern
Resilience patternsCircuit breaker, retry with back-off, bulkhead isolation
Service discoveryClient-side vs. server-side discovery, health checks
ObservabilityDistributed tracing (e.g. OpenTelemetry), structured logging, metrics
DeploymentContainerisation, orchestration with Kubernetes, rolling vs. blue-green deploys

What order should you tackle a microservices design question in?

Working through a structured sequence stops you from jumping to implementation details before the interviewer is sure you understand the problem.

  1. Clarify requirements and scale. Ask about expected request volume, the team structure, and whether the company is migrating a monolith or starting fresh. The answer changes your whole approach.
  2. Define the domain boundaries. Identify the core bounded contexts (e.g. Orders, Inventory, Payments) before naming any services. Draw the lines around business capability, not technical layers.
  3. Choose a communication strategy. Decide which service-to-service calls need a synchronous response and which can tolerate asynchronous messaging via a broker like Kafka or RabbitMQ.
  4. Address data ownership. Assign one service as the authoritative owner of each data entity. Then explain how other services stay consistent using events or read-model replicas.
  5. Plan for failure. Walk through what happens when one service goes down. Name the patterns you'd use (circuit breaker, dead-letter queues, idempotent retries) and why.
  6. Discuss observability and deployment. Mention distributed tracing, a centralised log aggregator, and how you'd ship changes without downtime.

Hitting all six steps, even briefly, signals that you think end-to-end rather than stopping at the happy path. That is the gap that separates a passing answer from a strong one at every difficulty level in this quiz.

Key facts

  • Tarmac has 37 System Design interview questions on this topic, 10 of them on this page, at difficulty 1–5 of 5.
  • Tarmac last reviewed these System Design interview questions on 20 July 2026.

At a glance

Questions10 shown · 37 in the bank
Difficulty1–5 of 5
FormatsMultiple choice, True / false, Ordering, Multiple answer, Short answer, Flashcard, Design exercise

What you'll review

  1. microservices

Practice questions

System Design/sd-architecture/microservices

Which of the following best describes the core principle of a microservices architecture?#

Options

Show answer

A microservices architecture breaks the application into small, independently deployable services, each owning a specific business capability. This is the defining characteristic of microservices — as opposed to a monolith, which packages everything into one unit. Services communicate over a network (e.g., HTTP/gRPC) and each manages its own data store.

Why:

Microservices architecture decomposes an application into small, loosely coupled services, each responsible for a distinct business capability and deployable independently. This contrasts with a monolith (option A), which packages everything together. Microservices typically avoid shared databases (option C) and shared memory (option D) in favor of well-defined network APIs.

System Design/sd-architecture/microservices

In a microservices architecture, it is considered a best practice for multiple services to share a single, centralized database so they can easily query each other's data.#

Options

Show answer

False — sharing a single centralized database across microservices is an anti-pattern. It creates tight coupling between services, making independent deployment and schema evolution very difficult. The recommended practice is for each microservice to own its own dedicated data store and expose data to other services only through well-defined APIs.

Why:

Sharing a single database across multiple microservices is an anti-pattern known as the 'shared database' anti-pattern. It creates tight coupling between services, making it hard to evolve schemas independently or scale services separately. Best practice dictates that each microservice owns its own data store, and services access each other's data through well-defined APIs.

System Design/sd-architecture/microservices

A development team is building a new feature using microservices. Arrange the following steps in the correct order for decomposing a monolith into microservices:#

Put these in order

Show answer

The correct order is: (1) Identify bounded contexts and business capabilities, (2) Define API contracts, (3) Extract the service with its own data store, (4) Deploy independently behind an API gateway. You must understand domain boundaries first, agree on interfaces before coding, isolate data, and finally route live traffic — each step depends on the previous one.

Why:

The standard approach to decomposing a monolith starts with identifying bounded contexts — logical groupings of related business capabilities (domain-driven design). Next, you design API contracts so other services know how to interact with the new service before writing any code. Then you extract the service along with its own database, eliminating shared-database coupling. Finally, you deploy the service independently and route traffic through an API gateway, validating the decomposition in production.

System Design/sd-architecture/microservices

In a microservices architecture, Service A needs to call Service B to complete a user request. Service B is temporarily unavailable. Which pattern is most appropriate to prevent Service A from exhausting its own resources (e.g., thread pools) while Service B is down?#

Options

Show answer

The Circuit Breaker pattern is the most appropriate choice. It tracks failure rates to Service B and, once a threshold is exceeded, 'opens' the circuit so subsequent calls fail fast instead of blocking. This prevents Service A's thread pools from being exhausted waiting for a slow or unreachable dependency, allowing the system to degrade gracefully rather than cascade-fail.

Why:

The Circuit Breaker pattern monitors call failures to a downstream service and, after a threshold is crossed, 'opens' the circuit so that further calls fail immediately rather than waiting for a timeout. This prevents thread pools and other resources in the calling service from being exhausted while the dependency is down. Retries alone worsen the situation by consuming more resources. The Saga and Sidecar patterns address different concerns (distributed transactions and cross-cutting concerns, respectively).

System Design/sd-architecture/microservices

In a microservices architecture, each microservice should share a single centralized database with all other microservices so that data consistency is easier to enforce.#

Options

Show answer

This is false. A core microservices principle is that each service should own its own dedicated database ('Database per Service' pattern). Sharing a centralized database tightly couples services together — schema changes in one can break others, it creates a single point of failure, and it defeats independent deployability. Cross-service data consistency is handled through eventual consistency and patterns like Sagas.

Why:

One of the core principles of microservices architecture is that each service owns its own data store (the 'Database per Service' pattern). Sharing a single database creates tight coupling between services — a schema change in one service can break others, and the database becomes a single point of failure and a scaling bottleneck. Data consistency across services is instead handled through eventual consistency, events, or the Saga pattern.

System Design/sd-architecture/microservices

A client request arrives at a microservices system that uses client-side service discovery (e.g., Netflix Eureka + Ribbon / Spring Cloud). In this pattern the service consumer itself queries the registry and picks an instance. Place the following components in the order the request passes through, from the external entry point to business logic execution:#

Put these in order

Show answer

The correct order is: Load Balancer / Ingress → API Gateway → Service Registry lookup → Target Microservice. In client-side service discovery (e.g., Netflix Eureka + Ribbon), the API Gateway itself queries the Service Registry to find a healthy instance before forwarding the request, making the registry lookup a distinct step that occurs after the gateway and before the microservice.

Why:

In a client-side service discovery architecture (exemplified by Netflix Eureka + Ribbon or Spring Cloud LoadBalancer), the component that wants to call a downstream service is responsible for querying the Service Registry directly before forwarding the request. The canonical flow is: (1) The external Load Balancer / Ingress is the first hop — it terminates TLS and spreads traffic across gateway instances. (2) The API Gateway applies cross-cutting concerns such as authentication, rate-limiting, and routing logic. (3) The Gateway, acting as the service consumer, performs a Service Registry lookup (e.g., queries Eureka) to discover healthy instances of the target service and selects one (usually via a client-side load-balancing algorithm like round-robin). (4) The request is forwarded directly to the chosen Target Microservice instance, which executes the business logic. This four-step ordering is unambiguous for client-side discovery because the registry lookup is an explicit, runtime step performed by the gateway/consumer before it can forward the call — unlike server-side discovery (ALB + ECS) where the registry resolution is handled internally by the load balancer and is not a discrete step visible to the gateway.

System Design/sd-architecture/microservices

You are evaluating whether to decompose a monolith into microservices. Which of the following are genuine signals that a decomposition is warranted?#

Options

Pick every one that applies.

Show answer

The genuine signals are that different parts need to scale independently at very different rates, that teams are stepping on each other because ownership boundaries are unclear, and that one module needs a completely different technology stack (such as a GPU inference service). A small, simple app one team can own comfortably, or a team with no operational maturity — no service discovery, tracing, or on-call culture — are anti-signals: start with a modular monolith.

Why:

Microservices are a tool for specific organisational and scaling problems, not a default. Independent scaling needs (a) are the original scalability motivator — you add replicas of the hot service without touching the rest. Ownership boundaries that reduce team friction (b) address the Conway's Law argument: independent deploy trains let teams ship without waiting for each other. Polyglot technology requirements (c) are a genuine boundary — a GPU inference workload doesn't belong in the same process as a CRUD API. The remaining two are anti-signals. A small team with a cohesive codebase (d) takes on network overhead, distributed debugging, and operational complexity for no gain; start with a modular monolith. And (e) describes a team that will struggle with microservices: the operational primitives — service discovery, distributed tracing, on-call runbooks — must exist before the network boundaries do, or incidents become un-debuggable.

System Design/sd-architecture/microservices

When you split a monolith into microservices, how should you draw the service boundaries, and why does each service owning its own database matter?#

Show answer

Draw boundaries around business capabilities (or DDD bounded contexts) so that each service owns a cohesive area — orders, payments, inventory — rather than splitting by technical layer. A good boundary minimizes cross-service calls for a single operation and keeps a team able to ship that service independently. Each service owning its own database matters because it enforces loose coupling: no other service can reach into its tables, so the service is free to change its schema, and you avoid a shared database becoming a hidden coupling point and a single bottleneck. The cost is that data is now distributed, so a query spanning services needs an API call or an event, and a transaction across services needs a saga instead of a single ACID commit.

Why:

Good boundaries follow business capabilities / DDD bounded contexts, not technical layers, so each service is cohesive and a team can ship it independently with minimal cross-service chatter per operation. Database-per-service is the structural rule that makes this real: private data means no service can couple to another's schema, so each evolves freely and there's no shared-DB bottleneck. The trade-off is distributed data — cross-service reads become API calls or events, and cross-service writes need a saga rather than one ACID transaction. A shared database silently re-couples services and is the classic anti-pattern.

System Design/sd-architecture/microservices

What are the core trade-offs of splitting a monolith into microservices?#

Show answer

Microservices gain independent deployability (teams ship without coordinating a full release), targeted scalability (scale only the hot service), technology flexibility (choose the right tool per service), and fault isolation (one service crash doesn't bring down everything). The costs are network latency and failure modes that were formerly in-process function calls, distributed data consistency (no single ACID transaction across services), operational complexity (container orchestration, service discovery, distributed tracing), and testing overhead (you must test contracts between services, not just units). Microservices are usually the right call once team size and deployment frequency justify the coordination tax, not as a default starting point.

Why:

Interviewers look for candidates who can articulate the costs alongside the benefits. The biggest practical pitfalls are premature decomposition (splitting before you know the domain boundaries) and neglecting the distributed systems failure modes that appear once calls cross a network boundary.

System Design/sd-architecture/microservices

An e-commerce company runs a single large monolith (catalog, cart, checkout, payments, orders, inventory, shipping all in one deployable, one database). Deploys are slow and risky, one team's bug takes the whole site down, and they can't scale checkout independently of browsing. Design the decomposition into microservices and the platform that supports it.#

Show answer

Goals & when to split. The pains are concrete: coupled deploys, no fault isolation, and an inability to scale checkout independently of browsing (which is ~50× the traffic). Those justify splitting. But microservices aren't free — they trade in-process calls and ACID transactions for network hops, partial failure, and distributed-transaction headaches. So I split deliberately, by business value, not everywhere at once.

Service boundaries. I decompose by bounded context / business capability: catalog, cart, orders, payments, inventory, shipping. Each is high-cohesion and owns its domain logic and its data. I avoid the anti-pattern of slicing along database tables into chatty anaemic services — boundaries follow how the business reasons about the domain, so services stay loosely coupled.

Database decomposition. Each service gets its own datastore (database-per-service) — this is what actually breaks the shared-DB scaling ceiling and SPOF. Services no longer cross-join each other's tables; instead they expose APIs and emit events. The orders service stores the product id (and denormalises the few fields it needs) and fetches the rest from the catalog API, or subscribes to catalog change events. What we give up is the convenient cross-table join and strong cross-entity consistency — replaced by API calls and eventual consistency.

Communication & gateway. An API gateway fronts everything: it authenticates, routes to the right service, rate-limits, and can fan out/aggregate. Between services I pick per interaction: synchronous REST/gRPC for a read I need right now (get product), asynchronous events for 'order placed' / 'inventory changed' so producers don't block on consumers. Every synchronous call is wrapped with timeouts, retries (idempotent), and a circuit breaker so a slow dependency fails fast instead of hanging the caller.

Cross-service correctness (place order). Placing an order spans orders + inventory + payments — three databases, so no single ACID transaction. I use a saga: a sequence of local transactions with compensating actions. Orchestrated, an order orchestrator does: reserve inventory → charge payment → confirm order; if payment fails after the reservation, it fires the compensation release inventory. The order sits in a PENDING state until the saga completes, and the user sees pending → confirmed (or failed). This is eventually consistent but never permanently leaks reserved stock.

Migration & new failure modes. No big-bang. I use the strangler-fig pattern: keep the monolith running behind the gateway, peel out one service plus its data at a time, route that capability's traffic to the new service (feature-flagged), dual-write / shadow-read to validate, then cut over and delete the monolith's copy. New failure modes — partial failure (one service down), cascading failure (a slow dependency dragging callers down), and added latency from hops — are contained with circuit breakers, bulkheads (isolate resource pools per dependency), idempotent retries with backoff, and distributed tracing so a request can be followed across services.

Why:

Decomposing a monolith tests judgement, not just diagram-drawing. The two decisions that define the answer are where the boundaries go — by bounded context / business capability so services are loosely coupled and own their data, never by slicing a shared table into chatty anaemic services — and how to break the shared database, the actual scaling ceiling, via database-per-service reached incrementally with the strangler-fig pattern (peel out one service plus its data at a time, no big-bang). Once data is split, cross-service flows like 'place order' can't use a single ACID transaction, so the correct tool is a saga with compensating actions (reserve → charge → confirm, release on failure), accepting eventual consistency. The strong candidate also names the costs microservices add — partial and cascading failure, network latency — and contains them with an API gateway, circuit breakers, bulkheads, idempotent retries, and distributed tracing, rather than treating 'microservices' as an unqualified win.

Related interview questions

The other 27 questions

This page shows 10. A free account opens the rest and marks your answers, which a page of answers can't do. Miss one and it returns a few days later, then a week after that, until you stop missing it.

Start free

Free · the whole bank · 100 graded answers per 30 days · written feedback and job-ad quizzes on the paid plan

What moved, monthly

One email a month when the bulletin comes out: what moved in the markets we track, and the new question topics we published. Confirm your address to join. Unsubscribe any time.