Microservices Architecture and Service Decomposition Questions
Decomposing a system into services along bounded contexts, defining service boundaries and ownership, and managing the tradeoffs against a monolith. Covers cohesion, coupling, data ownership per service, the distributed-monolith anti-pattern, and when a modular monolith beats microservices. Emphasizes decomposition reasoning rather than any single framework.
A company is moving from roughly 20 to 200 services. Explain Conway's Law's practical impact on the resulting architecture and reliability, and propose an organizational structure and set of team boundaries (platform/infra teams, service-owning teams, shared libraries) that improves ownership clarity and reduces cross-team coupling at that scale.
Sample Answer
Direct answer
Going from 20 to 200 services multiplies the coordination surface roughly with the number of services, not linearly with headcount, so the organizational structure that worked at 20 services (loose conventions, informal coordination) breaks down well before 200; the fix is introducing explicit platform and infrastructure teams that own shared concerns, clear per-service ownership with no orphaned services, and enough standardization that a new service doesn't require reinventing deployment, observability, and on-call practices from scratch.
Structured elaboration
Conway's Law's practical impact at this scale: at 20 services, informal cross-team communication (a Slack message, a quick sync) is usually enough to coordinate a shared concern; at 200, the number of possible pairwise team interactions grows far faster than the team count itself, and informal coordination stops scaling, showing up as duplicated effort (multiple teams independently solving the same infrastructure problem), inconsistent practices (some services have solid observability, others none), and slower cross-cutting changes (a security fix that needs to land in every service takes far longer to propagate without a shared mechanism). The organizational fix mirrors the technical one: introduce dedicated platform/infrastructure teams whose job is providing the shared capabilities every service team would otherwise reimplement (a deployment pipeline template, a standard observability stack, a shared authentication library), reducing the coordination surface from "every team talks to every other team" to "every team talks to the platform team."
Worked example
A concrete structure: product-facing teams each own a small, clear set of services end to end (their own on-call, their own release cadence), a platform team owns the shared deployment pipeline, service templates, and core infrastructure every other team builds on, and a smaller number of specialist teams (security, data platform) own concerns that genuinely need central expertise and shouldn't be duplicated 200 times. Team boundaries at this scale should be reviewed periodically (not fixed forever at whatever they were when the org had 20 services), since a boundary that worked well at 20 services can become a bottleneck at 200 if, for example, one team ends up owning far more services than it can operate well.
Trade-offs and pitfalls
The most common failure at this scale is under-investing in the platform team's capacity relative to how many product teams depend on it, turning the platform team itself into the new coordination bottleneck; the platform team's own roadmap needs to be resourced and prioritized as seriously as any product team's, since if it can't keep up with demand, product teams start working around it with one-off solutions, which recreates the inconsistency the platform team existed to prevent. Reliability at scale also depends on this structure: a shared, well-maintained deployment and observability platform, rather than 200 independently-invented ones, is what makes it possible to have a consistent incident-response process across the whole fleet.
Compare polyglot persistence (each bounded context choosing its own storage technology) with a single database technology standardized across all bounded contexts. Discuss the trade-offs in operational overhead, developer autonomy, backup/restore/recovery complexity, and data-migration difficulty, and describe when polyglot persistence earns its added complexity.
Sample Answer
Direct answer
Polyglot persistence means each bounded context picks the storage technology that fits its own access pattern (a graph database for a recommendations service, a document store for a catalog service, a relational database for a transactional payments service), while single-database-technology-per-bounded-context still gives each service its own schema and its own database instance, but standardizes on one storage technology (usually relational) across all of them. Polyglot persistence is justified when a service's access pattern is genuinely a poor fit for the standard choice, not merely because a newer technology looks appealing.
Structured elaboration
The case for polyglot persistence: a service whose core operation is graph traversal (like finding connections between entities several hops apart) performs and scales dramatically better on a graph database than forcing that traversal into relational joins; a service that's fundamentally a high-write-throughput time series (metrics, events) is a much better fit for a time-series-optimized store than a general relational database. The case against defaulting to it everywhere: every additional storage technology in production is a new thing to operate (backup strategy, failover strategy, monitoring, and staff who actually know how to run it well), and a team spread across five different database technologies has a much smaller bench of people who can debug any one of them under pressure than a team standardized on one or two.
The trade-offs concretely: operational overhead scales roughly with the number of distinct storage technologies in production, not the number of service instances, so ten services all using the same relational database technology (even in separate schemas) is operationally simpler than three services each using a different specialized store. Developer autonomy goes the other way: a team that owns its own service and its own storage choice can move faster on its own roadmap without waiting for a shared database team's priorities, but that autonomy is exactly what makes a later data-migration or recovery effort harder, since there's no common tooling or shared expertise across a genuinely polyglot fleet. Backup, restore, and recovery complexity multiplies with each distinct technology, since a well-tested disaster-recovery runbook for a relational database usually doesn't transfer to a graph database or a time-series store.
Worked example
A pragmatic middle ground: standardize on one or two default storage technologies (say, a relational database for anything with clear transactional needs, and a document store for anything schema-flexible) that cover the vast majority of services, and reserve a genuinely specialized technology (graph, time-series, search index) for the specific services whose access pattern would be actively painful on the default, requiring an explicit justification and sign-off rather than letting every team pick whatever's currently popular.
Trade-offs and pitfalls
The failure mode on the polyglot side is technology sprawl: a dozen services each independently choosing whatever database is trendy, with no shared operational playbook, so an incident in any one of them requires expertise the rest of the org doesn't have. The failure mode on the standardization side is forcing an access pattern that's fundamentally a poor fit (heavy graph traversal, for example) into a relational model, producing queries that are slow, hard to maintain, and eventually get worked around with ad hoc caching layers that recreate the complexity a purpose-built store would have handled natively.
You're asked to recommend whether a decade-old, high-scale monolith (or modular monolith, expecting growth toward roughly 1 billion monthly users) should be broken into microservices. Present a decision framework covering technical, organizational, operational, and business criteria; a migration strategy with rough cost and velocity trade-offs; and a minimal-viable first split that achieves the highest return for the lowest risk. Include a scenario where staying monolithic is still the right call.
Sample Answer
Direct answer
For a decade-old, high-scale monolith, the recommendation is rarely "stay monolithic" or "go fully microservices"; it's a targeted decision framework that identifies the specific parts of the system whose independent scaling or independent team ownership is actually costing the business money today, extracts those first, and leaves the rest alone until it earns the same treatment. Presenting it as an all-or-nothing rewrite is both riskier (a full rewrite of a decade of business logic is a multi-year, high-failure-rate project) and usually unnecessary, since most of the pain in an aging monolith concentrates in a handful of hot spots.
Structured elaboration
The decision framework has four legs:
- Technical: which modules have the sharpest scaling mismatch with the rest of the system (a payment-authorization path handling 100x the load of an admin screen, for example), and which modules have accumulated the most operational risk (frequent incidents, long deploy times, brittle test suites)?
- Organizational: which modules are owned by teams that are actively blocked on each other's release schedule, versus modules nobody has touched in years and that carry no coordination cost today?
- Operational: what's the current cost of a full-monolith deploy (build time, test-suite time, blast radius of one bad change) compared to what a partial extraction would cost to build and run?
- Business: what's the actual dollar or reliability cost of the status quo (missed SLAs, engineer-hours lost to slow deploys, revenue at risk from an outage in a hot path) versus the cost and risk of a migration?
Given those four inputs, the framework picks a minimal-viable first split: the one or two modules where the technical, organizational, and business signals all agree, rather than the module that is merely easiest to extract technically. A concrete growth target, such as an expectation of reaching roughly a billion monthly users, sharpens the technical leg specifically: it tells you which modules are within striking distance of hitting a real scaling wall at that volume (and therefore belong near the front of the queue) versus modules whose load profile stays comfortably flat regardless of how large the user base gets.
Worked example
For a ten-year-old payments monolith, a realistic first split is the fraud-scoring path if it independently spikes under promotional traffic and is owned by a distinct team from the rest of checkout, even though other parts of payments (refunds, reporting) stay in the monolith for years longer. The migration plan for that one path covers: strangling the fraud-scoring code path behind a routing layer, standing up the new service against a read-only copy of the data it needs, dual-running it against production traffic to compare outputs before cutting over, and only then removing the old code path. Rough cost and velocity estimates come from the extraction size (lines of code, number of database tables touched, number of consuming call sites) rather than from the size of the whole monolith.
Trade-offs and pitfalls
The scenario where staying monolithic is still correct is a module with low change frequency, no independent scaling need, and a single owning team: extracting it produces the operational cost of a new service (deploy pipeline, monitoring, on-call surface) with none of the benefit. The most common failure mode in these efforts is scope creep, where a targeted first extraction turns into "let's redesign the whole payments platform," which reintroduces the risk of the big-bang rewrite this framework exists to avoid; the discipline of picking the smallest split that clears the bar on all four dimensions is what keeps the migration low-risk.
Describe the modular monolith architectural pattern as an intermediate step before adopting microservices. What are its benefits and drawbacks, and what technical and organizational decision criteria would lead you to recommend staying with a modular monolith versus moving to microservices?
Sample Answer
Direct answer
A modular monolith is a single deployable application whose internal code is organized into strictly-separated modules, each owning its own data and exposing a defined interface to the others, the same discipline microservices apply at the network boundary but enforced inside one process instead of across services. It buys most of the maintainability and clear-ownership benefits people associate with microservices (an engineer can reason about one module without understanding the whole codebase) while keeping the deployment, testing, and debugging story of a single application.
Structured elaboration
The main benefits are: one deploy pipeline and one set of infrastructure to operate, no network calls (and their associated latency and failure modes) between modules that used to be function calls, easier cross-module refactors (the compiler or a single test suite catches a broken contract immediately, instead of it surfacing later as a runtime failure between two independently-deployed services), and a natural stepping stone toward microservices if a specific module's traffic or ownership needs later diverge from the rest.
The main drawbacks are: the module boundaries are enforced by discipline and code review, not by a hard network boundary, so they erode more easily under schedule pressure than a boundary that would require actually calling a different service to violate; every module still shares the same deploy (so a bug in one module can still take down the process serving all of them, and a slow test suite in one module still blocks everyone's release); and a module can't scale independently of the others without scaling the whole process.
Worked example
Decision criteria for staying with a modular monolith rather than moving to microservices: the team is small enough that a shared deploy pipeline isn't a bottleneck, no single module has a materially different scaling profile from the rest, and the org values the lower operational overhead (fewer things to monitor, deploy, and keep backward-compatible) more than independent per-module deployability. The Shopify engineering team's widely-discussed decision to run a modular monolith at very large scale is a well-known real-world example: strict internal module boundaries with a shared deployable, extracting specific components to their own services only when a concrete scaling or ownership need justified it.
Trade-offs and pitfalls
The most common failure mode is treating "modular monolith" as a label rather than a discipline: without enforced module boundaries (linting rules, code-ownership checks, or architectural review that catches a module reaching directly into another module's tables), a modular monolith degrades back into an ordinary tangled monolith over time, at which point it has neither the deployability benefits of microservices nor the simplicity benefits of a genuinely modular codebase.
You must lead a cross-functional architectural decision while teams disagree about adopting microservices versus staying with a modular monolith. Describe how you would gather objective data, facilitate the technical discussion, build consensus, make a recommendation that balances technical and business goals, and create a measurable plan to validate the decision after the fact.
Sample Answer
Direct answer
When a cross-functional team is split on microservices versus a modular monolith, the way through is to replace the debate with data: define the two or three signals that would actually decide it (current deploy coordination cost, whether any component needs independent scaling, and team-ownership friction), measure them on the real system, and let the measured answer, not the strongest opinion in the room, drive the recommendation.
Structured elaboration
A workable process looks like this: first, separate the technical disagreement from the underlying interests, since "microservices vs. modular monolith" arguments are often proxies for real but unstated concerns (a team wanting more autonomy over its release schedule, or an SRE team worried about operational load from more moving parts); surfacing those interests directly is usually more productive than debating architecture in the abstract. Second, agree on what evidence would settle the disagreement before gathering it, for example current deploy-queue wait times, incident data showing whether failures are concentrated in a few components, and headcount growth projections for the next year, so the data collection isn't retroactively interpreted to fit whichever side is winning the argument. Third, run a small, time-boxed spike, such as extracting one candidate module behind a clean interface first inside the monolith, to surface real integration costs before committing to a full split. Finally, make the recommendation with an explicit, falsifiable success measure attached (for example, "deploy frequency for the extracted service should double within two quarters, or we roll the decision back"), so the decision doesn't become permanent by default just because it shipped.
Worked example
A concrete facilitation sequence: run a short workshop where each side states the specific outcome they're worried about (not the architecture they prefer), collect the deploy-cadence and incident data for the modules under debate, and present both sides with the same evidence before asking for a recommendation, rather than presenting a pre-formed conclusion and asking for buy-in. If the data shows one module already has a measurably different release cadence and on-call profile from the rest, that's the concrete justification for extracting just that module, which often resolves the broader disagreement by making the actual scope much smaller than "microservices vs. modular monolith" implied.
Trade-offs and pitfalls
The most common failure in this kind of facilitation is letting the loudest technical opinion win instead of the data, which produces a decision the losing side doesn't actually buy into and will relitigate at the next disagreement. The second common failure is presenting the recommendation as a permanent, unreviewable architectural commitment rather than attaching a measurable checkpoint; when the plan includes an explicit point to check whether the split delivered what it promised, disagreement about the initial decision matters much less because everyone knows it will be revisited with evidence.
Unlock Full Question Bank
Get access to all 37 Microservices Architecture and Service Decomposition interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.