Evolution of a Python Backend Architecture: From MVC to Microservices and Domain‑Driven Design
This article recounts the author's three‑year journey evolving a Python‑based SaaS backend from a simple MVC setup through service splitting and microservices, detailing architectural choices, performance challenges, optimization tactics, and the move toward domain‑driven design, while sharing practical lessons and resources.
The author worked as a backend developer for three years on a SaaS product serving HR, with web, Android, iOS, and mini‑program clients. The backend was built with Python and RESTful APIs to enable rapid iteration.
The architecture evolved through four major stages: 1) MVC, 2) Service splitting, 3) Microservices, and 4) Domain‑Driven Design.
1. MVC
Initially, a small team (<5) used Django to quickly prototype features, focusing on code conventions and inspection rules. Nginx handled load balancing, Django processed logic, Celery managed asynchronous tasks, Redis provided caching, and Nginx Push Module delivered real‑time notifications.
Problems and optimizations included using uWSGI with gevent for higher concurrency, redis‑py connection pooling, djorm‑ext‑pool for MySQL connections, and configuring Celery with gevent. As the number of Django apps grew, deployment became cumbersome because each release required restarting all Django services.
2. Service Splitting
As the team expanded, responsibilities were divided into separate services. Shared code was extracted into a common Python library, while databases and Redis remained shared initially. Inter‑service communication switched to HTTP with internal hosts pointing to internal addresses.
Issues arose from the unmaintained Nginx Push Module, leading to the creation of a Tornado + ZeroMQ service (tormq) for notifications. Lack of retries, error handling, and rate‑limiting in HTTP calls reduced reliability, and managing Nginx configurations became error‑prone.
3. Microservices Architecture
The ingress layer adopted Kong (OpenResty‑based) API Gateway, implementing custom authentication and rate‑limiting plugins. Service registration was automated via Kong’s admin API during deployment.
A custom RPC framework (doge) built on gevent + msgpack, with etcd for service discovery, provided client‑side throttling, high availability, and load balancing.
Technical choices included learning OpenResty and Golang, ultimately selecting Kong for its Lua‑based extensibility. A short‑URL service was built with OpenResty, and a cloud load balancer distributed traffic across a Kong cluster.
The team also evaluated Python‑based Thrift (thriftpy) and a Dubbo‑style RPC framework but settled on doge due to team size and skill constraints.
4. Domain‑Driven Design
The next step involved extracting a data‑service layer, where each bounded context exposed a single aggregate root via RPC. Application services depended on these data services, achieving better decoupling.
Although DDD was still in the learning phase when the author left, they expect the backend to continue evolving toward this design.
Summary
Architecture and technology choices should serve product and customer needs rather than follow trends blindly. Team composition and compromises shape the final design, and finding optimal solutions within constraints is the biggest challenge.
Service Mesh is highlighted as the emerging mainstream for microservice architectures, and the author plans to keep learning about it.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.
