Article
Nov 5, 2024

Microservices Can Wait

Getting Started

Every new project begins with a mountain of decisions. One of the biggest ones is how to structure your application. Oftentimes I’ve seen people choose to do microservices simply because it's what they’re familiar with. This is a critical mistake. Having just completed YC’s summer batch, I saw several startups start with microservices and immediately become mired in a large number of problems.

The majority of these can be grouped into three categories — lock-in, complexity, and reliability.

Lock In

By their nature, microservices require you to define what each service is responsible for. Akin to waterfall development, this means making structural choices before you’ve had a chance to observe the system. These definitions inevitably end up being incorrect, as you know the least about your domain in the beginning.

Complexity

Starting with microservices typically means adopting a tool like kubernetes, which while powerful, introduces significant orchestration and deployment work. This makes local development, testing, and consistent tooling much harder. While all of these problems are solvable, focusing on them at an early stage isn’t making your beer taste better.

Reliability

With a monolith, your application state is binary. With just 3 microservices, you now have 8 potential application states (2^n). Understanding your application becomes exponentially more complicated in a microservices world. This leads to hours of unnecessary DevOps work.

The Downsides

So what do we lose out on by avoiding microservices? The typical arguments for microservices are:

  • Independent scalability
  • Fault tolerance
  • Better DX/SDLC for the individual service

Why are these worth trading off for? Independent scalability and fault tolerance require you to have a sufficiently correct understanding of your domain boundaries in order to be useful. There are some cases where you may already have a deep understanding (e.g. re-implementing a system you’ve built before) but in most cases, the correct set of service boundaries is an emergent property that results from continually building and deepening your knowledge over time.

The Upsides

What are the benefits of starting with a monolith? It boils down to one thing: simplicity.

  • Deployments are straightforward
  • Rollbacks are straightforward
  • Writing tests across your application is easy
  • Refactoring or restructuring code is easy
  • Everything is easy to find

All of the above leads to minimal friction. New contributors can quickly jump into the codebase and understand how things work right away.

Solving for the future before you experience it is typically a mistake. You don’t know what you don’t know, and microservices magnify this fact.

Don’t solve for problems you don’t yet have, as it might prevent you from ever having them.