When Architects Overdesign: Tales of Microservices, MQ, Caches, and Database Chaos
The article humorously chronicles a series of real‑world over‑design incidents—excessive microservice splitting, needless multi‑database sharding, ubiquitous message‑queue usage, over‑engineered caching, design‑pattern abuse, and bloated database schemas—highlighting why simplicity (KISS) remains the best practice for backend systems.
Microservice Granularity
One interviewee argued that finer granularity is always better, even splitting a monolith by controller, service and DAO layers into separate services. The result was an explosion of tiny services with no clear business boundary, increasing operational overhead and inter‑service coordination cost.
Pre‑planned Database Schema
A five‑year architecture plan allocated three physical databases and 300 tables based on an assumed peak of three million orders per day. Developers were forced to follow complex routing rules to locate data, often having to query tables one‑by‑one during debugging because the data was spread across many sharded tables.
Ubiquitous Message Queues
Message queues (MQ) were used for almost every scenario, including:
Asynchronous SMS verification where the producer and consumer belong to the same service.
Logging business events via MQ to decouple log writers.
Low‑TPS scheduling tasks (e.g., appointment booking) to achieve peak‑shaving.
Replacing most inter‑service RPC calls with MQ to claim system decoupling.
These uses added latency, increased system complexity, and made tracing difficult.
Multi‑Level Caching (Guava + Redis)
A Guava in‑process cache combined with a Redis distributed cache was deployed across OA systems, corporate websites, messaging centers, settlement, supply‑chain and CRM platforms. The layered cache improved read latency but caused frequent data‑inconsistency incidents because cache invalidation logic was not uniformly applied across services.
Design‑Pattern Overuse
Developers were repeatedly forced to apply heavyweight patterns regardless of necessity:
Builder pattern for simple POJOs.
Strategy pattern for any if‑else block.
Abstract Factory, Proxy, Observer patterns for trivial responsibilities.
This resulted in verbose code, steep learning curves for newcomers, and reduced readability.
Excessive Many‑to‑Many Relationships
Database schemas were designed with an overabundance of junction tables. While some many‑to‑many relationships (e.g., students ↔ classes, students ↔ courses, teachers ↔ students) are legitimate, the design also produced nonsensical mappings such as a single exam score belonging to multiple students or a class‑hour balance shared across students, leading to data integrity problems.
Database Portability Advice
Some architects advocated for maximum database portability by:
Using Hibernate HQL to abstract vendor‑specific syntax (e.g., limit vs. rownum).
Avoiding stored procedures to keep business logic out of the database.
Writing standard SQL to reduce future migration risk.
In practice, the team never needed to migrate databases, making the effort largely unnecessary.
Redundant Data Validation
One team re‑validated data after reading it from the database under the assumption that external actors might modify the data directly. This “defense‑in‑depth” validation duplicated checks already performed at write time and added processing overhead without measurable benefit.
Configuration‑Centric Business Logic
Numeric thresholds and business constants (e.g., HashMap.size()>0, gender code 1 for male, product status 2 for offline) were externalized to a configuration center to allow runtime changes without redeployment. While flexible, this practice scattered core business rules into configuration files, making the codebase harder to understand and increasing the risk of misconfiguration.
Conclusion
The recurring theme is over‑design: excessive service granularity, premature sharding, indiscriminate use of MQ and caches, pattern fetishism, and over‑engineered schemas. Adhering to the KISS (Keep It Simple, Stupid) principle—using the simplest architecture that satisfies functional requirements—helps maintain system reliability, reduces operational cost, and eases future evolution.
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.
dbaplus Community
Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.
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.
