← All practice sets
ArchitecturePractice · 10 questions

Architecture

Architecture questions about boundaries and trade-offs: monoliths and microservices, hexagonal design, events, sagas, CQRS, outbox, microfrontends, Conway's law, and splitting services.

Answer out loud or on paper before revealing. If your answer misses a key point, revisit the linked guide or explainer.

  1. Q1Junior

    Monolith or microservices: how do you decide?

    Reveal model answer

    Microservices let teams deploy, scale, and choose technology independently, but they add a large fixed cost: network calls that fail, distributed data and transactions, versioned contracts, and the deployment, monitoring, and tracing needed to run many services. Martin Fowler calls this the microservice premium, and argues it only pays off once a system and organization are too complex to work in one codebase. So the default for a new product or a small team is a well-structured monolith, splitting out services when there is a concrete driver: independent team ownership, very different scaling or reliability needs, or isolation of a risky component. Most successful microservice architectures started as monoliths that were split along boundaries learned over time.

    WHAT A STRONG ANSWER COVERS

    • Microservices trade code complexity for operational and distributed-systems complexity.
    • The premium: CI/CD, observability, contracts, distributed failure handling.
    • Start with a monolith; split for concrete organizational or scaling reasons.
    • Boundaries are hard to get right early and expensive to move later across a network.

    RED FLAGS

    • "Microservices scale better" with no mention of what needs to scale.
    • One service per database table or per entity.
    • Microservices that share one database and must deploy together (a distributed monolith).

    LIKELY FOLLOW-UPS

    • What signs would tell you it is time to split a monolith?
    • What is a distributed monolith, and how do teams end up with one?

    SOURCES

  2. Q2Mid

    What is a modular monolith, and how do you keep its modules from turning into a big ball of mud?

    Reveal model answer

    A modular monolith is one deployable application whose code is split into modules aligned with business domains (orders, billing, shipping), each exposing a small public API and owning its own data, so it keeps the simple deployment and in-process calls of a monolith with most of the boundary benefits of services. The boundaries only hold if they are enforced: module-level visibility rules, dependency checks in CI (Shopify built tooling to flag calls and data access outside a component's public API), no reaching into another module's tables, and an explicit dependency graph without cycles. Well-enforced modules are also the cheapest path to microservices later, because an extraction becomes replacing an in-process interface with a network one.

    WHAT A STRONG ANSWER COVERS

    • Organize by domain, not by technical layer.
    • Public module APIs and private internals.
    • Data ownership per module, even within one database (separate schemas).
    • Automated boundary enforcement in CI.
    • A stepping stone to extraction when a real need appears.

    RED FLAGS

    • Folders named by layer (controllers, models, services) described as modules.
    • Modules joining directly across each other's tables.
    • Relying on code review alone to enforce boundaries.

    LIKELY FOLLOW-UPS

    • How would you handle a transaction that spans two modules?
    • How would modules communicate: direct calls, in-process events, or both?

    SOURCES

  3. Q3Mid

    Explain hexagonal architecture (ports and adapters). What problem does it solve?

    Reveal model answer

    Hexagonal architecture, described by Alistair Cockburn, puts the application's domain logic at the center and lets it talk to the outside world only through ports, which are interfaces the application defines; adapters implement those ports for specific technologies. Driving (primary) adapters such as HTTP controllers, CLI commands, or tests call into the application; driven (secondary) adapters such as database repositories, message publishers, and payment clients are called by it. Dependencies point inward, so business rules can be tested without a database or web framework and an infrastructure choice can be swapped by writing a new adapter. The cost is more indirection, which is not worth it for thin CRUD services.

    WHAT A STRONG ANSWER COVERS

    • Domain logic in the center, independent of frameworks and I/O.
    • Ports are interfaces owned by the application; adapters implement them.
    • Driving versus driven sides.
    • Testability: run use cases with in-memory adapters.
    • Overhead not justified for simple CRUD.

    RED FLAGS

    • Defining ports that mirror the ORM's API, leaking persistence concerns inward.
    • Thinking it is about having exactly six sides.
    • Business rules living in controllers or adapters.

    LIKELY FOLLOW-UPS

    • How does hexagonal architecture relate to clean or onion architecture?
    • Where would transaction boundaries live?

    SOURCES

  4. Q4Senior

    What are the trade-offs of an event-driven architecture?

    Reveal model answer

    First clarify which pattern you mean, because Fowler separates four: event notification ("something happened", receivers call back for details), event-carried state transfer (events carry the data so consumers keep local copies), event sourcing, and CQRS. Events decouple producers from consumers, absorb load spikes, and let new consumers be added without changing the producer. The costs are that the overall business flow is no longer visible in any single place, consistency becomes eventual, delivery is usually at-least-once and sometimes out of order so consumers must be idempotent, and schema changes to events are contract changes. You also need tracing across async hops, dead-letter handling, and replay tooling.

    WHAT A STRONG ANSWER COVERS

    • Distinguish notification, state transfer, event sourcing, and CQRS.
    • Benefits: decoupling, buffering, extensibility.
    • Costs: hidden flow, eventual consistency, duplicates and ordering.
    • Events are public contracts that need versioning.
    • Operational needs: correlation IDs, DLQs, replay.

    RED FLAGS

    • "Events make services fully decoupled." They couple on the event schema and semantics.
    • Using events for request/response interactions that need an immediate answer.
    • Publishing events outside the database transaction with no outbox.

    LIKELY FOLLOW-UPS

    • How do you evolve an event schema used by five consumers?
    • How would you debug a business flow that spans six async consumers?

    SOURCES

  5. Q5Senior

    How do you keep data consistent across services: sagas or two-phase commit?

    Reveal model answer

    Two-phase commit gives atomicity across resources through a coordinator that asks every participant to prepare and then commit, but participants hold locks while waiting, the coordinator is a blocking point of failure, and most modern brokers and SaaS APIs do not support it; PostgreSQL warns that prepared transactions are for external transaction managers and should not be left open. A saga instead runs a sequence of local transactions, each publishing an event or command for the next step, and on failure runs compensating transactions that semantically undo earlier steps (refund, release inventory). Sagas can be choreographed through events or orchestrated by a central coordinator, which is easier to follow for long flows. They give up isolation, so intermediate states are visible and you need countermeasures such as pending states or semantic locks.

    WHAT A STRONG ANSWER COVERS

    • 2PC: prepare and commit phases, blocking, coordinator failure, limited support.
    • Saga: local transactions plus compensating actions.
    • Choreography versus orchestration trade-offs.
    • No isolation: design for visible intermediate states.
    • Each step needs reliable messaging (outbox) and idempotency.

    RED FLAGS

    • Assuming a compensating transaction is a rollback (an email that was sent cannot be unsent).
    • Using 2PC across microservices over HTTP.
    • Ignoring what happens if a compensation itself fails.

    LIKELY FOLLOW-UPS

    • Design the saga for placing an order: payment, inventory, shipping.
    • When is a single database transaction a better answer than either?

    SOURCES

  6. Q6Senior

    When would you use CQRS or event sourcing, and when would you avoid them?

    Reveal model answer

    CQRS separates the model used to change data from the model used to read it, which helps when reads and writes have very different shapes or scale, for example a complex domain with many denormalized query views. Event sourcing stores every state change as an immutable event and derives current state by replaying them, which gives a full audit trail, temporal queries, and the ability to build new projections later. Avoid both for CRUD-shaped domains: Fowler warns that CQRS adds risky complexity for most systems and should be applied only to specific bounded contexts, and event sourcing makes schema evolution, replays that touch external systems, GDPR deletion, and eventual consistency of read models into everyday problems. Often a reporting database, a materialized view, or an audit table gives the benefit for a fraction of the cost.

    WHAT A STRONG ANSWER COVERS

    • CQRS: separate write and read models; event sourcing: events as the source of truth.
    • They are independent; you can use either without the other.
    • Good fits: complex domains, audit-heavy domains, very different read and write loads.
    • Costs: eventual consistency, event versioning, replay side effects, data deletion.
    • Simpler alternatives: read replicas, materialized views, audit logs.

    RED FLAGS

    • Applying CQRS and event sourcing to the whole system by default.
    • Believing event sourcing requires CQRS or vice versa.
    • No plan for evolving or upcasting old events.

    LIKELY FOLLOW-UPS

    • How do you handle a user's right-to-erasure request in an event-sourced system?
    • How would you rebuild a projection without downtime?

    SOURCES

  7. Q7Senior

    What is the transactional outbox pattern, and what problem does it solve?

    Reveal model answer

    A service often needs to update its database and publish a message, and doing both directly is a dual write: if the process crashes between them, or the transaction rolls back after the message was sent, the two disagree. With an outbox, the service writes the message to an outbox table in the same database transaction as the business change, so both commit or neither does. A separate relay then publishes outbox rows to the broker, either by polling the table or by tailing the database's transaction log (change data capture, for example Debezium). The relay can publish a message more than once if it crashes after sending, so consumers must be idempotent, and you need to clean up or partition the outbox table.

    WHAT A STRONG ANSWER COVERS

    • Names the dual-write problem.
    • Outbox row committed atomically with the business change.
    • Relay via polling publisher or log tailing (CDC).
    • At-least-once delivery: idempotent consumers, message IDs.
    • Ordering per aggregate and outbox table housekeeping.

    RED FLAGS

    • Publishing to Kafka inside the database transaction and calling it atomic.
    • Publishing after commit with a retry loop and assuming that is enough.
    • Forgetting that consumers will see duplicates.

    LIKELY FOLLOW-UPS

    • What is the inbox pattern on the consumer side?
    • How would you preserve per-order event ordering through the relay?

    SOURCES

  8. Q8Mid

    When do microfrontends make sense, and what do they cost?

    Reveal model answer

    Microfrontends split a web frontend into independently built and deployed applications, usually one per business area owned by a vertical team, composed into one product through server-side includes, iframes, runtime JavaScript loading (for example Module Federation), or web components. They make sense when several teams are blocked on one frontend release train, or when you need to migrate a legacy frontend incrementally. The costs are duplicated dependencies and bigger payloads, inconsistent UX unless there is a shared design system, harder cross-app state and routing, and development environments that differ from the composed production page. Build-time integration via npm packages brings back lockstep releases, which defeats the purpose.

    WHAT A STRONG ANSWER COVERS

    • An organizational scaling tool more than a technical one.
    • Composition options: server-side, iframes, runtime JS, web components.
    • Costs: payload duplication, UX consistency, operational complexity.
    • Shared design system and thin, explicit contracts between apps.
    • Incremental migration of a legacy frontend is a strong use case.

    RED FLAGS

    • Adopting microfrontends with one team.
    • Sharing a global mutable store across microfrontends.
    • Composing through npm packages and calling it independent deployment.

    LIKELY FOLLOW-UPS

    • How would microfrontends share authentication state?
    • How do you keep performance budgets with five teams shipping JavaScript?

    SOURCES

  9. Q9Mid

    What is Conway's law, and how does it affect architecture decisions?

    Reveal model answer

    Conway's law says an organization designing a system will produce a design that copies its communication structure: teams that talk constantly produce tightly coupled components, separate teams produce separate modules joined by interfaces. So architecture and team structure must be designed together: a service boundary that cuts across a team, or a component shared by three teams, will be fought over. The inverse Conway maneuver deliberately shapes teams around the business capabilities you want the system to have, so that the desired architecture emerges and each service has one owning team. Reorganizing teams without changing the code, or the reverse, rarely works on its own.

    WHAT A STRONG ANSWER COVERS

    • System structure mirrors communication structure.
    • Service boundaries should match team ownership.
    • Inverse Conway maneuver: design teams for the target architecture.
    • Shared components without a clear owner become bottlenecks.

    RED FLAGS

    • Treating it as a joke rather than a design constraint.
    • Splitting services by technical layer (a frontend team, an API team, a database team) and expecting independent delivery.

    LIKELY FOLLOW-UPS

    • How would you assign ownership of a shared authentication service?
    • What would you do if the org chart changes every six months?

    SOURCES

  10. Q10Senior

    How would you extract a service from an existing monolith?

    Reveal model answer

    Pick a boundary by business capability that changes often or has distinct scaling needs, and start with something fairly decoupled to build the deployment, observability, and on-call muscle. Use the strangler fig approach: put a routing layer in front, build the new service beside the monolith, and move traffic for that capability gradually, keeping a rollback path. Move the data with the logic, because a service that still reads the monolith's tables is not independent: introduce an API or events for the data, dual-write or sync during migration, then cut over ownership. Avoid new calls back from the service into the monolith, and retire the old code path once traffic has moved so you do not maintain both forever.

    WHAT A STRONG ANSWER COVERS

    • Choose by business capability and change frequency, starting with an easier edge.
    • Strangler fig: route traffic incrementally with rollback.
    • Data ownership moves with the capability.
    • Minimize dependencies back to the monolith.
    • Finish the job: delete the old path.

    RED FLAGS

    • Big-bang rewrite of the whole system.
    • Extracting the code but leaving the service sharing the monolith's database.
    • Starting with the most entangled core domain first.

    LIKELY FOLLOW-UPS

    • How would you migrate the data without downtime?
    • How do you test the new service against the old behavior in production?

    SOURCES