← Back to Blog

Why We Migrated Our Monolith to Microservices (And What We Learned)

The Problem With Our Monolith

Three years ago, Geek Labs’ core platform was a classic Rails monolith. It worked beautifully until our team grew past 15 engineers and deployments started taking 45 minutes. A single bug in the billing module could take down the entire API. Something had to change.

What We Did

We adopted a strangler fig pattern — gradually extracting services from the monolith rather than rewriting everything at once. We started with the authentication service, then payments, then notifications.

The key decisions that helped us:

  • Kafka for async communication between services kept things decoupled
  • A dedicated platform team handled the shared infrastructure so product engineers could focus on their domains
  • Feature flags let us roll out incrementally without big-bang cutover risk

What Didn’t Work

Distributed tracing was an afterthought. We spent two weeks debugging a latency issue that turned out to be a cascade of N+1 queries across three services. If we’d instrumented with OpenTelemetry from day one, we’d have caught it in hours.

Contract testing between services also lagged behind. We had a few painful incidents where a service changed its API without notifying downstream consumers.

The Outcome

Today our deployments take under 4 minutes. Each team ships independently. Our on-call load dropped by 60% in the first six months.

Would we do it again? Absolutely. But we’d invest in observability and contract testing from week one.