Datadog 用 Claude+Cursor 做测试驱动迁移:操作从45分钟缩至秒级的AI重构
Datadog 的 Stream Router 团队最近干了一件事:把一套跑在 FoundationDB 上的 KV 路由系统迁移到了 PostgreSQL。你可能觉得这没什么特别的。
但他们用了一个你可能没试过的方法——让 Claude 在测试的约束下写代码。AI 不决定做什么、不决定怎么做,它只负责在测试已经定义好的轨道上执行。
你可能也在想:「用 AI 做代码迁移?不就是给 prompt 让它写吗?」
Datadog 的经历告诉你:不是这样写的。一次关键的生产迁移,操作耗时从 45 分钟降到约 1 秒,存储缩小 40 倍,数据库成本降低 90%。
这组数据来自 Datadog 工程师 Arnold Wakim 最近分享的内部实践。整个迁移的关键不是用了多强的模型——Claude 而已。真正让项目成功的,是他们设计的一套测试驱动 AI 重构的三阶段方法论。
一、先看问题:Stream Router 卡在哪了
Stream Router 是 Datadog 指标管线的路由 API,最初基于 FoundationDB 实现 KV 模型。初期跑得挺好,但随着路由表膨胀,问题开始冒出来:
- KV 数据库开始触及事务大小限制
- 最耗时的操作因数千次顺序往返,跑到 45 分钟
- 代码里不得不用应用层逻辑模拟关系数据库的 foreign key 行为——拉几万条 entry 到进程里自己拼
这不是小修小补能解决的了。团队决定重设计 Schema,从 KV 模型迁移到 PostgreSQL 关系模型。
但问题来了:这是一套正在线上的生产系统,新 Schema 定了,旧代码几千行,全手动重写?还是全扔给 AI?
两种都不靠谱。他们选了第三条路。
# Datadog 的三阶段输入模式(伪代码)
def refactor_with_ai(method_name, old_code, new_schema):
# Phase 1: 让 AI 描述意图
intent = claude.describe(f"这个 {method_name} 函数的目的是什么?")
# Phase 2: 测试驱动生成
failing_test = test_framework.make_test(method_name, new_schema)
attempts = 0
while not failing_test.passed and attempts < 3:
new_code = claude.generate(
old_impl=old_code,
new_schema=new_schema,
failing_test=failing_test
)
failing_test.run(new_code)
attempts += 1
return new_code
# Phase 3: Blue/Green 验证交给 infra 层
二、三阶段方法论:不是让 AI 自主编程,是用测试约束 AI
从 Wakim 的分享看,这三个阶段的设计很精准。每一阶段都有明确产出、有检验标准、有人类介入点。
Phase 1:让 Claude 描述意图
第一个阶段不是写代码,而是写描述。对 Stream Router 中每个关键函数,团队先让 Claude 读取旧代码,输出一份自然语言的行为描述——这个函数做什么、输入输出是什么、边界条件有哪些。
这个阶段的价值在于显性化隐性知识。很多函数写了好几年,功能早被人遗忘了。Claude 生成的描述文档充当了后续重构的「蓝图」。
Phase 2:测试驱动代码生成
这是整个方法论的核心。对每个需要重构的方法,团队构造了一个三件套输入:
旧实现 —— 原来的代码,告诉 Claude 当前逻辑
新 Schema —— PostgreSQL 的表结构定义
一个会失败的测试 —— 用新 Schema 的预期行为写测试
Claude 根据这三个输入写新代码。然后跑测试。通过了?下一个。没通过?调整 prompt 重来。
注意一个关键设计:测试失败不是意外,是工作流的一部分。 团队刻意构造「会失败的测试」作为输入——不是让 Claude 一次写对,而是让测试说话,告诉 Claude 哪里不对。
这跟大多数「给一个 prompt 让 AI 全量生成」的做法完全不同。测试在这里充当了 AI 行为的边界控制器——AI 可以自由发挥,但测试决定了它的输出是否被接受。
Phase 3:Blue/Green 双跑 + 对比验证
代码改完了,但是改对了吗?在传统重构里,这个问题靠人工 Code Review 回答。在 Datadog,答案靠并行验证。
两套 Stream Router 实例同时运行——旧的 FoundationDB 版和新的 PostgreSQL 版。同一个请求打到两套系统,各自产生路由响应。
然后一个专门的 Validator 服务在每个集群中周期性地比对新旧两个实例的输出。发现不一致?立刻告警。
Feature Flag 控制客户端流量路由,灰度切流。有问题的切回去修好再切。
这个验证体系的意义在于:它把「AI 写的代码对不对」的判断从人的责任变成了系统的责任。 人只需要在 Validator 告警时介入。其他时候,让系统自己验证。
三、三个使能要素
Wakim 在分享中特别强调了,如果不是这三个要素都已到位,这套方法论跑不起来。
强代码模块化。 Stream Router 在 PostgreSQL 上实现了一套和 FoundationDB 版完全相同的 API 接口。这意味着修改一个后端实现时,调用方代码一行都不需要改。没有这个条件,测试驱动 AI 重构的 scope 会扩大很多倍——改一个方法要牵出一串上下游,测试用例的写法和验证难度都指数上升。
完整测试套件。 这是整个方法论的基石。没有测试,AI 生成代码的「正确性」就只能靠人工审查,退回到了最慢的方式。Wakim 在最后总结时直接说:测试套件的强壮程度,决定了你有多大把握信任 AI 生成的代码。
并行基础设施。 Blue/Green 双跑听起来贵——两套系统同时跑,硬件翻倍。但对一次关键生产迁移来说,这套基础设施省掉的「上线后发现问题→回滚→排查→重试」的成本,远比多跑一套实例高。
四、Claude 做不到的:人类仍然不可替代
这可能是整篇文章里最有价值的部分 —— Datadog 团队坦诚地记录了 Claude 的短板。
「Niche optimizations such as batching, UNNEST tricks, and common table expressions required human input. The AI-generated queries returned the right results but issued far more round trips than necessary.」
翻译成人话:AI 写出来的代码逻辑上是对的,但性能上不行。
Claude 能写出正确的 JOIN、正确的 WHERE 过滤,但不会主动优化查询——不会用 UNNEST 替代逐行处理、不会写 CTE 减少子查询、不会做批量操作减少往返。这些优化需要人类来写第一版。
但好消息是:一旦人类示范过一次优化模式,Claude 能在后续的方法中复现同样的模式。 团队发现,他们手动写完一个优化版后,Claude 在后续类似方法中开始模仿这个模式。
这印证了当前 AI 编码工具的一个普遍规律:AI 是优秀的「模仿者」,但不是「发现者」。 人类负责发现优化模式、设计架构边界、定义验收标准。AI 负责在划定范围内高效执行。
还有一个实用的教训:Token 消耗。 团队把完整的测试输出 dump 喂给 Claude,Token 消耗非常高。Wakim 建议裁剪测试输出后再提交,只保留关键差异部分。
# 迁移效果对比
# 指标 迁移前(FoundationDB) 迁移后(PostgreSQL)
# 操作耗时 45 分钟 ~1 秒
# P99 延迟 数百毫秒 个位数毫秒
# 存储占用 基准 1/40
# 数据库成本 基准 1/10
# CPU/内存 高 显著下降
五、这些经验对你有用吗?
你所在的公司大概率没有 Datadog 那个级别的路由表和 45 分钟的查询。但这套方法论的价值在于它的可迁移性。
| 场景 | 能借用什么 |
|---|---|
| 日常代码重构 | 给 AI 输入「旧代码 + 新接口 + 失败测试」,让测试当裁判 |
| 数据库迁移 | Blue/Green 对比验证,Validator 服务比对输出 |
| 新项目启模 | 先测试后代码,不写测试就不让 AI 写代码 |
| 代码审查 | 用测试结果替代主观判断,「通过了就 OK」 |
三条可以直接抄进团队技术方案的原则:
第一,测试不是验收环节,是执行环节。 大多数人写测试是「验证写完的代码对不对」。Datadog 是先写测试,再让 AI 填代码,测试是 AI 的「工作指令」。
第二,AI 不自主决策。 他们会做什么、要做到什么标准,由人类定义。AI 只在划定好的轨道里执行。这个「人类在环内」的设计,才是生产级 AI 编码的正确姿态。
第三,并行验证是最好的保险。 新系统上线前,新旧双跑一段时间,让系统替你发现差异。不要事后才对比——要在上线前就有对比基准。
这让我想起之前写过的 Spotify 73% PR 由 AI 生成那篇。两篇结合起来看,你会发现一个共同的模式:高效的 AI 编码不是让 AI「干活」,而是让 AI「在测试的约束下执行」。 成功的团队都在做同一件事——把 AI 的「创造力」缩小、把 AI 的「执行力」放大。
如果你所在的团队也在尝试用 AI 做代码重构或生产迁移,不妨试试这套三阶段方法论。先写一个会失败的测试,再把代码交给 AI——让测试说话,你只做裁判。
更多推荐



所有评论(0)