Senior Architecture 7 min read

Microservices vs Monolith — Architecture Decision Guide

The Interview Question

When should you use microservices vs a monolith? What are the tradeoffs?

Expert Answer

A monolith is a single deployable unit containing all application logic. Microservices decompose the application into small, independently deployable services that communicate over the network (HTTP/REST, gRPC, or message queues). The honest take: most teams should start with a monolith. Microservices solve organizational scaling problems (many teams working independently), not technical ones. A well-structured monolith handles millions of users — Shopify runs a massive monolith. Microservices add significant operational complexity: service discovery, distributed tracing, inter-service communication failures, data consistency across services (saga pattern), independent deployment pipelines, and the need for container orchestration (Kubernetes). The tradeoffs: monoliths are simpler to develop, test, deploy, and debug. One codebase, one deployment, one database. But they become painful when the codebase gets so large that build times are slow, teams step on each other, and a bug in one module can bring down everything. Microservices shine when you have multiple teams that need to deploy independently, when different components have vastly different scaling needs (video processing vs user profiles), or when you need fault isolation (one service crashing shouldn't take down the whole system).

Key Points to Hit in Your Answer

  • Start with a monolith unless you have a specific reason for microservices
  • Microservices solve organizational problems (team independence), not just technical ones
  • Monolith → modular monolith → microservices is a natural progression
  • Microservices costs: network latency, distributed debugging, data consistency, operational complexity
  • Conway's Law: system architecture mirrors team communication structure
  • Service boundaries should align with business domains (Domain-Driven Design)
  • The 'distributed monolith' anti-pattern: microservices that are tightly coupled and must be deployed together

Code Example

// Monolith: simple function call
class OrderService {
  async createOrder(userId, items) {
    const user = await userService.getUser(userId);     // in-process call
    const inventory = await inventoryService.check(items); // in-process call
    const order = await orderRepo.save({ userId, items });
    await emailService.sendConfirmation(user.email, order); // in-process call
    return order;
  }
}

// Microservices: network calls with failure handling
class OrderService {
  async createOrder(userId, items) {
    try {
      const user = await httpClient.get(`http://user-service/users/${userId}`);
      const inventory = await httpClient.post('http://inventory-service/check', items);
      const order = await orderRepo.save({ userId, items });
      await messageQueue.publish('order.created', { order, user });
      return order;
    } catch (err) {
      // What if user-service is down? Retry? Circuit breaker? Fallback?
      // What if order saved but email service failed? Saga rollback?
      // This is where microservices complexity lives
    }
  }
}

What Interviewers Are Really Looking For

Senior question — they want pragmatism, not microservices hype. The strongest answer starts with 'default to a monolith' and explains when to migrate. Mentioning the distributed monolith anti-pattern shows real-world experience. Conway's Law and DDD for service boundaries are senior-level signals. If asked 'how do you handle transactions across services?', the Saga pattern is the answer.

Practice This Question with AI Grading

Reading about interview questions is a start — but practicing with real-time AI feedback is how you actually get better. Goliath Prep grades your answers instantly and tells you exactly what you're missing.

Start Practicing Free →