How Qunar Revamped Its Hotel Service Architecture with Domain‑Driven Design
This article details Qunar's journey from a monolithic hotel information system to a domain‑driven microservice architecture, covering the evolution path, design principles, reconstruction patterns, DDD implementation steps, COLA framework adoption, and the resulting improvements in organization and development efficiency.
Architecture Evolution Path
The system progressed through four stages that match business growth:
Monolith (giant‑stone) : All business logic resides in a single codebase to minimise early‑stage cost.
Service‑oriented : Functions are split into independent services as traffic and domain complexity increase; governance and abstraction are introduced.
Platform : Over‑fine granularity is consolidated, reusable capabilities are extracted, and domain autonomy is supported.
Mid‑platform : An enterprise‑level reuse platform is built with data inter‑connectivity and rapid response to business change.
Architecture choice is driven by current and foreseeable business requirements rather than a notion of “good” or “bad”.
Business System Reconstruction Background
Qunar’s hotel‑basic‑information subsystem faced pandemic‑induced market pressure and suffered from excessive service granularity—more than ten microservices per business function—resulting in high maintenance cost and slow feature delivery. Core user flows include list, detail, hotel‑info and booking pages, each aggregating hotel data for the end‑user.
Reconstruction Modes and Architecture Selection
Three migration strategies were evaluated:
Refactorer : Add an abstraction layer on top of the existing system and gradually improve internals.
Eliminator : Build a new system outside the legacy codebase, then phase out old services.
Evolutionary : Incrementally refactor core business logic from an MVP, then migrate peripheral services.
Qunar adopted a hybrid of Eliminator and Evolutionary to minimise impact while delivering core functionality quickly.
Business‑Driven Microservice Evolution with DDD
The domain‑driven design (DDD) process consisted of the following steps:
Define a unified business vision and terminology.
Analyse the problem domain and split it into sub‑domains (core, supporting, generic).
Identify bounded contexts and draw a context‑dependency map, avoiding circular and bidirectional dependencies.
Model the domain using aggregates, entities and value objects, aiming for high cohesion and low coupling.
Map the domain model to code layers using the COLA framework.
The COLA framework provides a clean layered structure:
Adapter : Multi‑endpoint adaptation (e.g., HTTP, Dubbo).
Client : External service contracts.
App : Application use‑case orchestration (executors, schedulers).
Domain : Aggregates, entities, value objects, domain services (business rules).
Infrastructure : Repository implementations, ACLs, external resource adapters.
Common : Shared utilities and base classes.
COLA’s layered design naturally supports CQRS (Command‑Query Responsibility Segregation), allowing commands to mutate state in the Domain layer while queries are served read‑only from the Infrastructure layer.
Key Technical Practices
Conway’s Law & Inverse Conway : System structure mirrors organisational communication; Qunar deliberately reshaped teams to match the desired bounded contexts.
Bounded Context Principles :
Minimal completeness – each context can fulfil its responsibilities without external help.
Self‑fulfilment – a context decides its own responsibilities.
Stable space – external changes do not break the context.
Independent evolution – internal changes do not affect external contracts.
Three‑No Rule for Context Maps : No bidirectional dependencies, no circular dependencies, no excessively long dependency chains.
Microservice Granularity : A microservice may host multiple bounded contexts but must belong to a single sub‑domain type (core, supporting, or generic) to avoid coupling core and non‑core concerns.
Implementation Highlights
Using COLA, the team organised code as follows (illustrative package layout):
com.qunar.hotelinfo
├─ adaptor // adapters for HTTP, Dubbo, etc.
├─ client // external API contracts
├─ app // use‑case orchestrators
├─ domain // aggregates, entities, value objects
│ └─ hotel // Hotel aggregate root, Room entity, PriceVO, etc.
├─ infrastructure // repository implementations, ACLs
└─ common // shared utilitiesDomain events identified during event‑storming (e.g., HotelCreated , PriceUpdated ) were modelled as immutable value objects and published via an asynchronous message bus, enabling eventual consistency and decoupling of read‑side services.
Results and Metrics
Microservice count reduced by 33 % (21 → 13 services).
Average development effort per feature dropped below 3 person‑days , yielding a 52 % faster response to business needs.
Domain ownership became explicit, reducing inter‑team friction and improving testability.
Unified language and bounded‑context mapping lowered defect rates and accelerated onboarding of new developers.
Takeaways
Align architecture with business evolution; avoid over‑engineering early‑stage systems.
DDD surfaces hidden domain knowledge, enabling systematic decomposition of complex domains.
Team consensus on bounded contexts and language is essential for successful migration.
Adopting a proven layered framework (COLA) accelerates implementation while providing clear separation of concerns.
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.
