我做过一个内容平台的推荐系统,从只服务国内一个地区,逐步扩展到东南亚、中东几个海外地区。每扩展一个地区,团队都要重新回答同一个问题:这块逻辑该塞进现有核心,还是该在本地单独长一份。两头都有教训——当初图省事把国内的推荐链路直接拷贝到第一个海外地区,半年后两边规则各改各的,一次账号安全策略调整要在两份代码里各修一遍,改漏一处线上就出问题;后来矫枉过正,想把所有地区提前收进一个"统一推荐平台",结果发现每个地区的内容审核口径、数据出境要求、机房归属都不一样,抽象出来的接口没用几周就要打补丁。

两次教训背后,是同一件事没做清楚:系统还没分清什么已经稳定、什么仍在变化。

大一统与定制化是一条滑动变阻器

统一与定制不是二选一,而是一条随条件调整的滑动变阻器。基础能力牢固、领域知识清楚、业务模式稳定时,统一可以减少重复、让协作有共同语言;反过来,当业务仍在探索、地区差异很大,或团队尚未理解领域边界时,保留定制化往往更诚实。

在那个推荐系统里,用户行为埋点、召回排序的基础算法框架,几个地区上线一年多都没有本质变化,这部分越早统一越省事;但内容分发要不要落地在境内机房、哪些内容类目允许跨境访问、审核规则谁说了算,这些是每进一个新地区就会重新出现分歧的地方,早期硬统一反而是在给自己挖坑。

先区分核心与变化

后来我们重新梳理了一遍:用户画像模型、召回排序引擎、基础埋点协议,这些经过国内和第一个海外地区两轮验证之后,行为一致、没有再出现地区特有的例外,可以放进共享核心;而内容合规策略、数据存储位置、跨境访问白名单、本地化的内容分级标准,这些本质上是各地区法规和内容生态决定的,只能放在明确的扩展层,由本地团队按各自规则实现。

关键不是把所有内容放进同一份代码,而是让每个差异有清楚的位置。当时我们踩过的坑是:中东那个地区的内容审核规则一开始被塞进了共享的内容分发模块,导致东南亚团队每次改分发逻辑都要先弄清楚一段跟自己无关的审核代码是干什么的,改动经常互相绊住。拆开之后,各地区的审核规则单独维护,共享模块只负责通用的分发调度,这类冲突才消失。

在稳定后再抽象

抽象应当跟着重复且稳定的模式走。国内和第一个海外地区的召回逻辑长得像,还不足以说明已经找到了真正的领域模型——直到第三个地区上线,同样的召回排序需求、同样的埋点字段又出现了一遍,而三地的差异也能被清楚说成"数据出境策略不同"而不是"逻辑本身不同",这时候把召回排序抽成共享模块、把出境策略做成可配置项,才有底气。

每次准备抽象前,我们会问几个问题:这条规则是不是已经在多个地区稳定出现,而不是巧合地长得像;差异到底是参数不同,还是流程本身不同;一个地区改规则,是不是必须连累其他地区一起改;抽出来之后谁负责维护、谁来评审改动。答不清楚就先让各地区各写各的,比强行搭一个通用平台更安全——延迟抽象是在为正确的设计攒证据,不是放弃设计。

所有权比目录结构更重要

共享模块需要明确谁维护、谁能改、改动怎样评审。那次拆分之后,召回排序模块归中台团队负责,各地区的合规策略归本地团队负责,跨团队修改共享模块不是禁区,但要让模块负责人理解影响范围、让测试覆盖真正跑在几个地区上的公共路径。

从复制到共享的阶段

早期复制并不总是坏事——它让团队更快看清哪些差异是真的。真正花时间的是把这些差异记下来:哪些规则在多个地区反复出现、哪些差异有了稳定的名字。只有到这一步,才值得把它提炼成接口、配置或共享模块。

那个推荐系统后来的样子,是核心召回排序共享、内容合规和机房部署本地化,两边各自演进也没再互相拖累。多地区系统要的从来不是"代码只有一份",而是共享带来真实收益,变化不伤害其他地区。这次拆分让团队明白的道理很朴素:先把哪些是稳定的、哪些是随时可能变的分清楚,再决定用什么方式组织代码。

后来我又把这个问题放到内容、搜索、交易和增长等更多业务域里看了一遍,发现“差异应该放在哪里”只是第一步,下一步还要回答“差异怎样被配置、编排和治理”。相关的配置化架构,整理在《让差异停留在配置层:多业务域平台的架构设计》里。