How NetEase Yanxuan Built a Scalable Warehouse Dispatch Platform: Architecture & Lessons
This article explains how NetEase Yanxuan transformed its warehouse dispatch service from duplicated, monolithic code into a modular, extensible platform by abstracting common processes, designing extension points, using dependency injection, and orchestrating business flows to improve development efficiency, system stability, and traceability.
Warehouse Dispatch Service Overview
NetEase Yanxuan, a fast‑growing e‑commerce brand, operates multiple self‑owned and partner warehouses across the country and connects with many courier providers. The core function of the warehouse dispatch service is to find the optimal fulfillment path for each order by selecting the appropriate warehouse and courier.
The service currently integrates more than ten business products, divided into two categories: online order dispatch for various channels and offline strategy simulation. The global view of the service is illustrated in the diagram below.
Why Platform‑Based Technical Refactoring?
Initially the service only handled a single scenario, but as Yanxuan grew it began to support more than ten online and offline scenarios, leading to two separate codebases: a "chimney" architecture and a monolithic bloated codebase. This caused duplicated development, low efficiency, and tight coupling between business logics.
The main pain points are:
Bloated and duplicated code reduces development efficiency and makes onboarding new developers difficult.
Coupled business logics cause changes in one scenario to affect others, harming system stability and increasing regression testing cost.
Understanding the logic of a single scenario requires traversing the entire codebase.
Continuing this approach would further slow business response and exacerbate these issues, so a platform‑based refactor is needed to unify and manage dispatch processes.
Service Requirements
Beyond rapid response to business changes and system stability, the dispatch service also needs:
Flexible strategy components that can be assembled, evaluated, and optimized per business.
A way to manage strategy versions so that changes are traceable rather than requiring code modifications.
Goals of Platform‑Based Refactoring
The refactor aims to solve six core problems: duplicate construction, platform extensibility, business coupling, process orchestration, strategy evaluation/optimization, and strategy traceability. The required technical features are:
Reusability – maximize code and capability reuse for new business integration.
Extensibility – provide extension mechanisms for personalized business flows.
Isolation – avoid cross‑scenario interference to keep the system stable.
Configurable Process Orchestration – enable rapid assembly of modules and data to build various business processes, supporting runtime module replacement.
Strategy Closed‑Loop – combine offline simulation, online gray‑release, and metric comparison to guide strategy selection and optimization.
Traceability – store business flows and strategies with unique IDs for easy routing and historical lookup.
These features translate into higher development efficiency, improved system stability, and data‑driven decision making.
Platformization Approach
The overall implementation follows these steps:
Unify the dispatch model and abstract a common warehouse‑dispatch workflow.
Reserve extension points to support platform extensibility.
Adopt modular development.
Orchestrate business processes.
Handle business onboarding and identity routing.
Abstracting a Common Dispatch Workflow
By analyzing existing code, a generic workflow with ten nodes was extracted. This abstraction clarifies business logic, reduces duplicated code, and serves as a stable core similar to a micro‑kernel, while extensions reside in the outer layer.
Designing Extension Points
To support diverse business needs, the platform defines extension points (interfaces) and corresponding extensions (implementations). Modules can be viewed as classes; each module may contain extension points and can also serve as an extension for other modules, forming a tree‑like structure.
For example, the “available inventory” node uses a template‑method pattern: the abstract InventoryService defines the overall calculation, while subclasses provide concrete implementations for fetching on‑hand, in‑transit, and hold inventories.
Modular Development with Dependency Injection
Java classes are developed using DI (Guice). Configuration data and extensions are injected at runtime, enabling low coupling and high testability.
public class AppDispatchModule extends AbstractModule {
@Override
protected void configure() {
bind(DispatchService.class).toInstance(new DispatchService());
// Bind inventory service and its dependencies
bind(InventoryService.class).to(InventoryServiceRealTimeImpl.class);
bind(HoldInventoryService.class).to(HIServicePromiseImpl.class);
// Additional bindings...
}
}A JSON configuration can replace hard‑coded bindings, allowing dynamic updates without code changes.
{
"BizRoleId":"app_dispatch",
"InventoryService":"com.yanxuan.xxx.InventoryServiceRealTimeImpl",
"HoldInventoryService":"com.yanxuan.xxx.HIServicePromiseImpl"
}Business Process Orchestration
The platform assembles independent modules at runtime via Guice, creating a complete workflow per business scenario. Each scenario can have its own AbstractModule, eliminating large if‑else blocks and improving isolation.
// Example of creating a dispatcher for a specific business role
AbstractModule bizFlow = new AppDispatchModule();
Injector injector = Guice.createInjector(bizFlow);
DispatchService dispatchService = injector.getInstance(DispatchService.class);
dispatchService.dispath();Business Onboarding and Identity Routing
The routing layer determines the business identity ID from the request, selects the corresponding module, and thus the appropriate workflow. It also supports legacy requests without an explicit ID and enables gray‑release or A/B testing.
New scenarios include a business identity ID in the request.
Legacy scenarios are mapped to an ID using existing rules.
Routing facilitates gradual rollout and region‑based segmentation.
Platform Architecture
The platform consists of five layers:
Business Product Layer – external services for each business scenario, where processes are composed.
Routing Engine Layer – determines the business identity ID and selects the corresponding workflow.
Orchestration Engine Layer – assembles core capability components and extensions into a complete process, identified by a unique ID.
Core Capability Layer – provides the unified dispatch model, extension points, extensions, and configuration instances.
Unified Logging & Metrics Layer – collects execution logs into a data warehouse, calculates metrics (e.g., warehouse split ratio, courier load, cost, next‑day delivery rate), and feeds them back for continuous improvement.
Conclusion
The article presents a lightweight, quickly deployable platform solution that avoids heavyweight workflow engines or plugin systems. By reducing code size, lowering onboarding cost, and simplifying new‑business integration, the refactor significantly boosts development efficiency.
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.
Yanxuan Tech Team
NetEase Yanxuan Tech Team shares e-commerce tech insights and quality finds for mindful living. This is the public portal for NetEase Yanxuan's technology and product teams, featuring weekly tech articles, team activities, and job postings.
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.
