Bay Flow Platform: Service‑Side API Architecture and Evolution at DiDi
DiDi’s Bay Flow platform transforms its service‑side API into a configurable, layered “travel middle‑platform” that routes front‑end requests through a flow layer and reusable ability components, using the Dukang framework’s transports, steps, and factors to support dozens of ride‑hailing categories across PHP and Go while ensuring isolation and high reuse.
DiDi’s ride‑hailing business requires a highly flexible service‑side API layer that can support dozens of product categories (taxi, express, luxury, etc.) while keeping isolation and reuse across them. The Bay Flow platform was created to turn the API layer into a "travel middle‑platform" that bridges front‑end requests with downstream order, pricing, and settlement services.
Project background : In the traditional "cone" traffic model, multiple business lines share a large middle‑platform but have separate front‑ends. DiDi’s ride‑hailing adopts a "diamond" model where a unified API entry point routes traffic to a common business middle‑platform and finally to the base platform. This model introduces two challenges: (1) platform‑level cross‑BU requirements (e.g., holiday fees, pandemic controls) and (2) category‑specific variations (e.g., taxi meter pricing).
Service‑side API responsibilities : The API must handle three core duties – traffic coloring (identifying category, scenario, function), process stitching (orchestrating downstream services), and data rendering (producing category‑specific responses).
Bay Flow platform evolution :
Version 1.0 (2017‑2018): solved rapid category addition and code isolation via configuration and plugin mechanisms.
Version 2.0 (2018): introduced domain‑driven design, splitting a monolithic module into vertical domain services to reduce complexity.
Version 3.0: separates the API logic into two layers – a flow layer (process orchestration) and a capability component layer (business functions). The flow layer handles the macro ride‑hailing process, while capability components (e.g., broadcast, pricing) are configurable per category.
Dukang framework : To implement the 3.0 design, DiDi built the Dukang framework, which orchestrates the API execution through the following core concepts:
Transport : the process carrier; each category can extend a BaseTransport and override specific steps.
Step : an atomic business fragment within a Transport; steps can be overridden for large‑scale differences.
StepRuntime : a read‑only data bus that connects steps and feeds the Ability layer.
InputSource : isolates external request data and provides a uniform input for transports.
TransportFactor : decision factors (e.g., product_id, car_level) that guide which Transport implementation is selected.
Ability : reusable capability components (e.g., dispatch order, virtual phone) that expose configurable modes; category‑specific extensions are added via plugins.
The framework supports both PHP (legacy) and Go (new services). Below is a PHP configuration example and the corresponding execution flow:
{
"name": "ConfirmOrder",
"transports": {
"default": "\\DuKang\\Transport\\ConfirmOrderBaseTransport",
"express": "\\DuKang\\Express\\Transport\\ConfirmOrderExpressTransport",
"luxury": "\\DuKang\\Luxury\\Transport\\ConfirmOrderLuxuryTransport",
"taxi": "\\DuKang\\Taxi\\Transport\\ConfirmOrderTaxiTransport"
},
"steps": [
{"step_id": "fetchInfoStep", "description": "获取基本信息"},
{"step_id": "confirmTravelStep", "description": "确认行程信息"},
{"step_id": "confirmBillStep", "description": "确认计价信息"},
{"step_id": "checkStep", "description": "成单检查"},
{"step_id": "fillOrderDetailStep", "description": "订单维度填充"},
{"step_id": "sendOrderCommandStep", "description": "订单处理操作"},
{"step_id": "sendDriverCommandStep", "description": "司机处理操作"},
{"step_id": "sendSchedulingCommandStep", "description": "调度处理操作"},
{"step_id": "buildResponseStep", "description": "构建响应"},
{"step_id": "asyncOperationStep", "description": "异步操作"},
{"step_id": "writeLogStep", "description": "日志处理"}
]
}
try {
$oBizConf = BizConfig::load($sConfigStr);
$oInputSource = new ConfirmOrderInputSource();
$oStepRuntime = new ConfirmOrderStepRuntime($oInputSource);
$oFlowScheduler = new FlowScheduler($oBizConf, $oStepRuntime);
$oTransportSelectFactor = new ConfirmOrderTransportSelectFactor($oInputSource);
if ($oFlowScheduler->selectTransport($oTransportSelectFactor)) {
$oFlowScheduler->run();
}
} catch (DuKangException $e) {
echo json_encode(['errno' => $e->getCode(), 'errmsg' => $e->getMessage()]);
} catch (\Exception $e) {
echo json_encode(['errno' => $e->getCode(), 'errmsg' => $e->getMessage()]);
}After the execution, the framework provides additional concepts such as Transport Factor, Ability modes, and configuration‑driven component selection, enabling both high reuse and fine‑grained isolation across the many ride‑hailing categories.
The article concludes with the directory layout of the PHP module (mirrored in Go) and a recruitment notice for senior backend engineers.
Didi Tech
Official Didi technology account
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.