← Back to Blog

Migrating Monoliths to Microservices: Lessons from E-Commerce

Tiago LeΓ£o β€’ β€’ 7 min read

During my time at Wowcher, I led one of the most challenging and rewarding projects of my career: transforming a monolithic e-commerce platform into a distributed microservices architecture. Here's what I learned.

The Starting Point

When I joined Wowcher as a Senior Software Engineer, the platform was a classic monolith. It worked, but scaling was becoming painful. As a high-volume deals platform processing thousands of transactions daily, we needed something better.

The tech debt was real. Deployments were risky all-or-nothing affairs. A bug in one feature could bring down the entire platform. Team velocity was suffering as developers stepped on each other's toes.

The Strategy

1. Strangler Fig Pattern

We didn't attempt a big-bang rewrite. Instead, we used the strangler fig pattern β€” gradually extracting services while keeping the monolith running. Each new feature was built as a microservice. Each refactored component was extracted carefully.

2. Choosing the Right Technologies

Our new stack emerged from practical needs:

  • Spring Boot for Java services β€” familiar to the team, battle-tested
  • Python services for specific use cases requiring rapid development
  • PostgreSQL as our primary database β€” reliable, scalable
  • Redis for caching and session management
  • DynamoDB for high-throughput scenarios
  • RabbitMQ for asynchronous communication
  • AWS (API Gateway, Lambdas, S3) for infrastructure

3. Infrastructure as Code

Every deployment had to be reproducible. We built Jenkins pipelines from scratch, containerized everything with Docker, and established clear deployment protocols.

The Hard Lessons

Database Decomposition is Painful

The hardest part wasn't the code β€” it was the data. Splitting a shared database into service-owned data stores requires careful planning. We had to:

  • Map data ownership clearly
  • Handle eventual consistency
  • Build robust sync mechanisms during migration

Testing Changes Fundamentally

Unit tests aren't enough in a distributed world. We invested heavily in:

  • Integration tests with test containers
  • Contract testing between services
  • End-to-end tests for critical paths

Monitoring Becomes Critical

With one monolith, you knew where to look when things broke. With 20+ services, you need observability built in from day one.

The Results

After two years of iterative migration:

  • Deployment frequency increased from weekly to multiple times daily
  • Mean time to recovery dropped dramatically
  • Team velocity improved as services could be developed independently
  • Scaling became straightforward β€” scale only what needs scaling

Key Takeaways

  1. Don't rewrite, migrate β€” The strangler pattern works. Keep the business running while you transform.
  2. Invest in CI/CD early β€” Automated pipelines are non-negotiable for microservices.
  3. Data strategy first β€” Figure out data ownership before you write code.
  4. Embrace eventual consistency β€” It's not a bug, it's a design pattern.
  5. Team structure matters β€” Conway's Law is real. Align teams with service boundaries.

Looking Back

The Wowcher transformation taught me that technical challenges are often easier than organizational ones. The technology choices matter, but getting buy-in from stakeholders, managing risk during migration, and keeping the team motivated through years of incremental work β€” that's where leadership really counts.


Have you undertaken a similar migration? I'd love to hear about your experience. Get in touch.