Rethinking 12306 Ticketing: A Domain‑Driven Design Model for Complex Train Reservations

This article analyses the unique business complexity of China's 12306 railway ticketing system, proposes a domain‑driven aggregate design centered on the train route, explains how to model seat availability and ticket issuance, and outlines a CQRS/event‑sourcing architecture to achieve strong consistency and high concurrency.

21CTO
21CTO
21CTO
Rethinking 12306 Ticketing: A Domain‑Driven Design Model for Complex Train Reservations

Preface

During the Spring Festival I came across an article stating that the business complexity of 12306 is far greater than that of typical e‑commerce sites such as Taobao. This observation motivated me to explore the core domain model of the 12306 system.

Another reason for writing this article is the suspicion that the current core domain model of 12306 is not well designed, which makes ticket‑purchasing logic extremely complicated, raises data‑consistency maintenance costs dramatically, and hinders high‑TPS ticket booking.

Requirement Overview

The core problem of 12306 is online ticket sales, involving two roles: users and the railway bureau. Users need to query seat availability and purchase tickets; the bureau needs to sell tickets. The system must support three core scenarios: query remaining tickets, purchase tickets, and the bureau’s ticket‑selling process.

Querying remaining tickets requires the user to provide departure station, destination station, and travel date, after which the system shows each train’s stations and seat‑type availability.

Purchasing tickets consists of reservation and payment; this article focuses on the reservation model.

Requirement Analysis

If a ticket is treated as a product, the problem looks similar to e‑commerce, but the number of possible tickets (SKUs) is huge because each pair of stations on a train creates a distinct ticket. For example, the G71 train with 17 stations and three seat classes yields 408 distinct tickets.

A ticket’s essential information includes departure time, departure station, destination station, train number, and seat number. For the system, a ticket is a credential that grants the holder a seat on a specific train segment.

Analyzing the train’s seat capacity shows that a seat can be sold for multiple non‑overlapping segments, allowing the number of sellable tickets to exceed the physical seat count. The key business rule is that, for every atomic segment (adjacent stations), the number of overlapping tickets plus one must not exceed the total seat count.

Model Design

Traditional E‑commerce Approach

Modeling each ticket segment as a separate product aggregate leads to an explosion of aggregates (e.g., 408 for G71) and requires updating many aggregates in a single transaction, causing high contention and potential deadlocks.

My Approach

Aggregate Design

The train (train‑route) should be the aggregate root responsible for ticket issuance. It stores the train number, seat count (by class), ordered list of stations, departure time, and the available quantity for each atomic segment. All ticket‑related decisions are made within this aggregate, ensuring strong consistency without database transactions.

How to Determine If a Ticket Can Be Issued

Given a reservation request, retrieve all atomic segments covered by the requested interval and attempt to decrement the available count for each segment. If all decrements succeed, the reservation succeeds; otherwise it fails.

Seat Allocation

The aggregate also maintains a pool of seats and the mapping between sold tickets and seats. When a reservation is possible, an algorithm selects a suitable seat, preferring reuse of already allocated seats to avoid mid‑journey seat changes.

Model Analysis Summary

Tickets are not core aggregates; they are the result of a reservation.

The train aggregate is the true core, handling availability checks, seat selection, atomic‑segment inventory updates, and storing sold tickets.

This design confines all state changes to a single aggregate, eliminating the need for distributed transactions while supporting high concurrency.

Architecture Design (Optional)

The system fits well with a CQRS architecture: the command side uses DDD and event sourcing (e.g., EN​ode) to process reservations, while the query side uses distributed caches for fast ticket‑availability queries.

Reservation Implementation

In‑memory + event sourcing allows each reservation to generate a single event, avoiding heavy database I/O and enabling rapid processing.

Ticket Query Implementation

Queries can be served from caches keyed by departure‑destination‑date or by atomic‑segment availability, ensuring near‑real‑time responses.

Conclusion

The article presents a domain‑driven model for 12306 that treats the train as the aggregate root, simplifies ticket issuance logic, and leverages CQRS and event sourcing to achieve strong consistency and high performance. Real‑world implementation would require close collaboration with domain experts.

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.

Backend ArchitectureDomain-Driven DesignDDDCQRSEvent Sourcingticketing systemtrain reservation
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

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.