From Monolith to Microservices: A Real‑World Online Supermarket Migration Story
This article walks through the evolution of an online supermarket from a simple monolithic website to a fully‑featured microservice architecture, highlighting the challenges, design decisions, component choices, monitoring, tracing, testing, and the trade‑offs of service mesh versus custom frameworks.
Initial Requirements
A few years ago, Xiao Ming and Xiao Pi launched an online supermarket with a basic website for browsing and purchasing products and a separate admin backend for managing users, items, and orders.
Growing Business and Early Problems
Rapid competition forced them to add promotions, mobile apps, and data analysis, leading to duplicated code, tangled interfaces, blurred service boundaries, performance bottlenecks, and painful deployments.
First Refactoring: Shared Services
They abstracted common capabilities into five public services—User, Product, Promotion, Order, and Data‑Analysis—allowing each application to call these services instead of duplicating logic.
Database Splitting and Messaging
To eliminate the shared‑database bottleneck, each service received its own database, and a message‑queue was introduced for real‑time communication.
Monitoring
Each component exposes a uniform /metrics endpoint; Prometheus scrapes these metrics and Grafana visualises them with alerts for memory, latency, error rates, etc.
Link Tracing
Using Zipkin (an implementation of Google’s Dapper), they inject traceId, spanId, parentId, and timestamps into HTTP headers to reconstruct request call trees.
Log Analysis
ELK (Elasticsearch, Logstash, Kibana) is deployed so logs from all services are indexed, searchable, and visualised, enabling fast root‑cause analysis.
Gateway and Service Governance
A central API gateway enforces authentication, provides a unified API catalogue, and can be applied per domain or globally.
Service Registration & Discovery
Services register themselves to a discovery system (e.g., Consul/Eureka) and obtain peer addresses automatically, supporting dynamic scaling.
Circuit Breaker, Degradation & Rate Limiting
When a downstream service fails repeatedly, the circuit breaker opens to return immediate errors; non‑critical features are degraded, and rate limiting protects services from overload.
Testing Strategy
End‑to‑end tests cover core user flows.
Service‑level tests validate each API.
Unit tests ensure code correctness.
Mock servers are used to isolate dependencies during service testing.
Microservice Framework vs. Service Mesh
They built a lightweight framework to handle metrics, tracing, logging, and registration, but faced upgrade coordination challenges. As an alternative, a sidecar‑based Service Mesh (data plane + control plane) provides non‑intrusive traffic management, though it adds memory overhead.
Conclusion
The migration demonstrates that microservices improve modularity and scalability but introduce new operational complexity; continuous monitoring, automated discovery, and disciplined governance are essential for success.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
