Migrating Monoliths to Microservices: Lessons from E-Commerce
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
- Don't rewrite, migrate β The strangler pattern works. Keep the business running while you transform.
- Invest in CI/CD early β Automated pipelines are non-negotiable for microservices.
- Data strategy first β Figure out data ownership before you write code.
- Embrace eventual consistency β It's not a bug, it's a design pattern.
- 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.