Operations 24 min read

From Monolith to Microservices: Real‑World Lessons and Practical Strategies

This article walks through the evolution of an online supermarket from a simple monolithic website to a fully split microservice architecture, highlighting the pitfalls of ad‑hoc growth, the need for service abstraction, monitoring, tracing, fault tolerance, testing, and the trade‑offs of frameworks versus service mesh.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
From Monolith to Microservices: Real‑World Lessons and Practical Strategies

This article introduces microservice architecture and its related components, explaining what they are and why they are used. It focuses on presenting a global view of microservices without diving into detailed component usage.

Initial Requirements

Several years ago, two founders built an online supermarket with a simple website for browsing and purchasing products and a separate admin backend for managing users, products, and orders.

Website

User registration and login

Product display

Order placement

Admin backend

User management

Product management

Order management

Because the requirements were simple, the initial system was built quickly as a monolith with a shared database.

Business Growth and Emerging Problems

Rapid competition forced the team to add promotions, mobile apps, and data analysis, leading to ad‑hoc code duplication, tangled interfaces, blurred service boundaries, performance bottlenecks, a shared‑database schema that could not be refactored, and cumbersome deployment processes.

Duplicate business logic across web and mobile apps

Inconsistent data sharing (direct DB access vs. API calls)

Services growing beyond their original responsibilities

Performance degradation in the admin backend after adding analytics

Database schema locked by multiple services

Database becoming a single point of failure under load

Complex, error‑prone release cycles

Team friction over ownership of shared functionality

Time for Change

Recognizing these issues, the team abstracted common business capabilities into independent services:

User Service

Product Service

Promotion Service

Order Service

Data‑Analysis Service

Each application now consumes data from these services, eliminating most redundant code.

Even after service separation, a shared database still caused performance and coupling problems.

Database became a performance bottleneck and single point of failure.

Data management grew chaotic as services directly queried each other's data.

Schema changes required coordinated updates across services.

To resolve this, the team split the database, giving each service its own persistence layer and introducing a message‑queue for real‑time communication.

With isolated databases, services could adopt heterogeneous storage technologies, such as a data warehouse for analytics or caches for high‑traffic services.

Monitoring – Detecting Failure Signs

In high‑concurrency distributed systems, failures can appear suddenly. The team built a monitoring stack using Prometheus to scrape metrics from exporters (e.g., RedisExporter, MySQLExporter) and Grafana for dashboards and alerts.

Tracing – Locating Faults

Each request may traverse multiple services. By propagating a traceId, spanId, parentId, and timestamps in HTTP headers, the system can reconstruct call graphs. The team used Zipkin (an open‑source Dapper implementation) and added an interceptor to inject tracing data.

Log Analysis

When log files become massive and distributed, a searchable log platform is essential. The team adopted the ELK stack (Elasticsearch, Logstash, Kibana) to ingest, store, and visualize logs, using file‑beat agents to ship logs to Logstash.

Gateway – Access Control and Service Governance

A gateway sits between callers and services, enforcing authentication and providing a unified API surface. The team chose a coarse‑grained approach: one gateway for external traffic, internal calls remain direct.

Service Discovery and Dynamic Scaling

Instances register themselves with a discovery service (e.g., Zookeeper, Eureka, Consul, Etcd). New instances are deployed without manual load‑balancer updates; the discovery layer handles registration, health checks, and client‑side load balancing.

Circuit Breaker, Service Degradation, and Rate Limiting

Circuit Breaker

If a downstream service fails repeatedly, the circuit breaker opens, returning errors immediately to prevent cascading latency.

Service Degradation

Non‑critical services can be gracefully degraded during outages to keep core functionality alive.

Rate Limiting

To protect services from overload, requests are throttled per time unit, optionally scoped to offending callers.

Testing Strategy

Testing in a microservice world occurs at three levels:

End‑to‑end testing of the whole system (expensive but most reliable).

Service‑level testing of APIs.

Unit testing of individual code units (fastest, but limited scope).

Microservice Framework

To avoid repetitive integration code, the team built a lightweight framework that handles metric exposure, tracing injection, log forwarding, service registration, routing, circuit breaking, and rate limiting. However, framework upgrades can be costly and require coordinated releases across many services.

Service Mesh – An Alternative Path

Instead of embedding logic in each service, a sidecar proxy can handle cross‑cutting concerns (traffic routing, security, observability). The data plane consists of sidecars; the control plane manages their configuration.

Conclusion – The Journey Continues

Microservices are not an end point; future directions include serverless, FaaS, and even a return to monoliths in some cases. The transformation described provides a practical roadmap for teams embarking on similar journeys.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

monitoringarchitectureMicroservicestestingService Meshtracingcircuit breaker
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.