Fundamentals 27 min read

How to Design Scalable, Maintainable Software Architecture: From Principles to Practice

This article explores how to build a robust engineering architecture by prioritizing product value, defining clear layered and DDD structures, selecting appropriate technologies, and establishing standards for exception, logging, monitoring, and team collaboration to achieve scalability, maintainability, reliability, security, and high performance.

dbaplus Community
dbaplus Community
dbaplus Community
How to Design Scalable, Maintainable Software Architecture: From Principles to Practice

Introduction

Software architecture must satisfy scalability, maintainability, reliability, security and high performance while being driven by product (business) value. The article presents concrete practices for achieving these qualities.

Value‑First Decision Making

When requirements are ambiguous, evaluate solutions from a commercial‑value perspective. Two common traps to avoid:

Accept everything – treating every product‑manager request as mandatory.

Technology‑driven – forcing the product to fit a clever technical implementation.

Eliminating these traps aligns development with product goals and facilitates sustainable iteration.

Architecture Design

1. Engineering Framework

Establish a baseline project skeleton that includes:

Standard directory layout and module dependency conventions.

Configuration files and code templates.

Unified interface contracts, exception coding, and log formatting.

2. Layered Architecture

Typical multi‑layer patterns (MVC, Hexagonal/Six‑sided) separate concerns and improve testability. The common layers are:

Data Access Layer – DAO/ORM (MyBatis, Hibernate) interacting with MySQL, HBase, Elasticsearch, etc.

Remote Call Layer – RPC or third‑party service adapters.

Transaction Management Layer – Cross‑cutting services such as distributed‑transaction coordinators.

Business Logic Layer – Core service orchestration.

Request Handling Layer – HTTP controllers, validation, routing.

Open Service Layer – Public APIs (REST/RPC) with gateway security and traffic control.

Presentation Layer – UI rendering (Thymeleaf, Vue, React, iOS).

Benefits: clear separation, easier maintenance, extensibility. Drawbacks: steeper learning curve, added complexity, longer initial development.

Layered architecture diagram
Layered architecture diagram

3. Domain‑Driven Design (DDD)

DDD places the domain model at the centre, isolating business concepts from technical details. The typical DDD stack consists of:

User Interface Layer – Web, RPC, MQ entry points.

Application Layer – Orchestration, validation, transaction boundaries.

Domain Layer – Entities, Value Objects, Aggregates, Domain Services, Events, Repositories, Factories.

Infrastructure Layer – Persistence, messaging, external utilities.

DDD excels for complex business logic, high maintainability and rapid iteration, but requires deep domain knowledge, cross‑team collaboration and higher technical expertise.

Technical Selection

Choosing technologies should balance business needs, team skills and long‑term costs. Evaluation dimensions:

Business requirements – functionality, performance, security, future expansion.

Technical characteristics – availability, scalability, maintainability.

Community support – active community, documentation, third‑party libraries.

Team expertise – avoid unfamiliar or overly complex tools.

Cost‑benefit – development, operation, licensing.

Risk assessment – maturity, known vulnerabilities, dependency chain.

Examples:

Object database db4o – stores objects directly, tiny DLL (~300 KB), no server needed. Suitable for embedded single‑node use, but introduces a single‑point‑of‑failure in distributed systems.

Fastjson – high‑performance JSON parser, widely used, but recent CVEs require frequent upgrades; security risk must be weighed.

JDK version alignment – Spring Boot 3 requires JDK 17; legacy systems on JDK 8 must consider migration cost versus new‑feature benefits.

Standardization & Consensus

1. Data Layering

Use distinct data transfer objects to prevent leakage of internal structures:

VO (View Object) – data for UI rendering.

DTO (Data Transfer Object) – payload for remote calls.

DO (Domain Object) – business‑level entities.

PO (Persistent Object) – ORM‑mapped persistence models.

Example: a table with 20 columns maps to a PO with 20 fields, but the front‑end only needs 10; a DTO with those 10 fields avoids exposing the full schema.

2. Object Reuse

Uncontrolled object scope leads to maintenance headaches. Mitigation strategies:

Define clear ownership and lifecycle in design documents.

Conduct regular code reviews to detect shared mutable objects.

Refactor “god objects” into smaller, purpose‑specific DTOs/VOs.

3. Exception Management

Two steps:

Capture – place try‑catch where continuation is required; otherwise catch at entry points for logging.

Handle – log stack trace, encode error codes (e.g., HTTP‑style), persist diagnostic data for later analysis.

Consistent encoding enables automated alerting and rapid root‑cause identification.

4. Log Management

Adopt a façade such as SLF4J with concrete implementations (Log4j2, Logback). Configure:

Pattern layout, output destinations, rotation policy.

Separate files per log level (INFO, WARN, ERROR).

Asynchronous logging for performance.

Periodic cleanup to avoid disk exhaustion.

Optional forwarding to ELK, Loki or other analysis pipelines.

5. Monitoring

Instrument the system for:

Resource metrics (CPU, memory, disk, network) – e.g., Prometheus + Grafana.

Log aggregation – ELK stack.

Security events – Snort/Suricata.

Business KPIs – request latency, error rate, throughput.

Distributed tracing – Zipkin, SkyWalking.

Alerting channels – email, WeChat, SMS.

Collaboration Scenarios

1. HTTP 414 (URI Too Long)

Root cause: Tomcat’s default maxHttpHeaderSize (≈8 KB). Three mitigation paths:

Increase the limit in server.xml (e.g., to 16 KB).

Support POST for large payloads instead of GET.

Trim unnecessary headers and cookies – the most sustainable fix.

Short‑term fixes (1 & 2) are easy but may affect many services; long‑term refactoring (3) reduces systemic risk.

2. Front‑end Business Logic vs. Pure Rendering

Considerations:

APP release cycles – front‑end bugs require user updates; back‑end fixes can be hot‑patched.

Clear responsibility boundaries – avoid duplicated validation.

Network overhead – moving static UI data to the front‑end reduces payload size.

Decision should minimise cost, avoid new problems and respect the product’s positioning.

Conclusion

Effective system engineering starts with a value‑first mindset, adopts a disciplined layered or DDD architecture, selects technologies based on concrete criteria, and enforces shared standards for data objects, exception handling, logging and monitoring. Practical dilemmas such as oversized GET requests or front‑end logic scope are resolved by weighing short‑term effort against long‑term maintainability, always aiming for low cost, minimal risk and alignment with product goals.

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.

monitoringSoftware ArchitectureMicroservicesException HandlingDomain-Driven Designlogginglayered architecturetechnical selection
dbaplus Community
Written by

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.

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.