惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
C
Cybersecurity and Infrastructure Security Agency CISA
S
Secure Thoughts
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
Arctic Wolf
www.infosecurity-magazine.com
www.infosecurity-magazine.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
W
WeLiveSecurity
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
Y
Y Combinator Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Forbes - Security
Forbes - Security
NISL@THU
NISL@THU
博客园 - 聂微东
G
Google Developers Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Schneier on Security
Schneier on Security
V
Vulnerabilities – Threatpost
V
V2EX
I
Intezer
S
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
L
LangChain Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
L
LINUX DO - 热门话题
P
Proofpoint News Feed
Microsoft Security Blog
Microsoft Security Blog
Project Zero
Project Zero
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
爱范儿
爱范儿
H
Hacker News: Front Page
B
Blog
T
Threatpost
Spread Privacy
Spread Privacy
H
Heimdal Security Blog
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
T
Threat Research - Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Cloudflare Blog

Datadog | The Monitor blog

Introducing our open source AI-native SAST Instrument and monitor Boomi integration flows with OpenTelemetry and Datadog Not all index scans are equal: How we cut query latency by over 99% Platform engineering metrics: What to measure and what to ignore Integrate Recorded Future threat intelligence with Datadog Cloud SIEM CI/CD security: threat modeling using a MITRE-style threat matrix CI/CD security: How to secure your GitHub ecosystem Ingress NGINX is EOL: A practical guide for migrating to Kubernetes Gateway API Operating agentic AI with Amazon Bedrock AgentCore and Datadog LLM Observability: Lessons from NTT DATA Introducing the Datadog Code Security MCP Capture and analyze custom heatmaps in Session Replay Understand session replays faster with AI summaries and smart chapters Monitor ClickHouse query performance with Datadog Database Monitoring How we designed empathetic alert sounds for on-call engineers Search and act across Datadog to resolve issues faster with Bits Assistant Measure the business impact of every product change with Datadog Experiments Analyzing round trip query latency Configuring JavaScript caches for better performance Introducing Bits AI Dev Agent for Code Security Datadog achieves ISO 42001 certification for responsible AI Monitor Nutanix clusters, hosts, and VMs with Datadog Monitor Juniper Mist in Datadog A new Host Map for modern infrastructure Annotate traces to improve LLM quality with Datadog LLM Observability What’s new in Cloud SIEM: AI-powered investigations, enhanced threat intelligence, and scalable security operations Explore Kubernetes with native OpenTelemetry data Monitor Oracle Fusion Cloud Applications with Datadog Announcing the Datadog Terraform provider v4.0.0 Scaling Kubernetes workloads on custom metrics How to design cloud environments for AI-powered threat analysis Monitor Aruba Central in Datadog How we centralize and remediate risks with Datadog Case Management Accelerate incident response with Datadog and ServiceNow Monitor your application and network load balancer logs Understanding Karpenter architecture for Kubernetes autoscaling Tools for collecting metrics and logs from Karpenter Monitor Karpenter with Datadog What your product data is actually saying Key metrics for monitoring Karpenter Securing Datadog’s platform in the AI age: The role of observability data Four ways engineering teams use the Datadog MCP Server to power AI agents Approaching your observability migration with the right mindset Meet the new Bits AI SRE: Deeper reasoning, twice as fast Key learnings from the 2026 State of DevSecOps study Use plain English to query your multi-cloud infrastructure in Resource Catalog Simplifying troubleshooting across the user journey with Datadog Synthetic Monitoring Protect your OCI resources with Datadog Cloud Security This Month in Datadog - February 2026 Amazon EC2 security: How misconfigured and public AMIs expand your cloud attack surface Enable end-to-end visibility into your Java apps with a single command Measure and improve mobile app startup performance with Datadog RUM Evaluating our AI Guard application to improve quality and control cost Identify untested code across every level of your codebase Make use of guardrail metrics and stop babysitting your releases Monitor Versa Networks SD-WAN performance in Datadog Improve performance and reliability with APM Recommendations Remediate transitive vulnerabilities faster with Datadog Software Composition Analysis Generate audit-ready vulnerability and compliance reports with Datadog Sheets Monitor Fortinet FortiManager performance in Datadog Improve test coverage across codebases with Datadog Code Coverage Move fast, don’t break things: Consistent testing standards at scale Enrich logs with ServiceNow CMDB context before routing to any SIEM or logging tool Monitor Lustre with Datadog Make faster, better product decisions with Datadog Product Analytics Surface and remediate runtime posture issues with Workload Protection Findings Protect agentic AI applications with Datadog AI Guard How to optimize JavaScript code with CSS Trace Google Pub/Sub workloads in Cloud Run with Datadog Detect human names in logs with ML in Sensitive Data Scanner How we cut our NLQ agent debugging time from hours to minutes with LLM Observability Debug PostgreSQL query latency faster with EXPLAIN ANALYZE in Datadog Database Monitoring Datadog acquires Propolis Unify and correlate frontend and backend data with retention filters Scale compliance across global frameworks with Datadog Cloud Security Monitor Arista VeloCloud SD-WAN performance with Datadog Building reliable dashboard agents with Datadog LLM Observability Simplify log collection and aggregation for MSSPs with Datadog Observability Pipelines Mitigation for Node.js denial-of-service vulnerability affecting Datadog APM Automate flaky test fixes with the Bits AI Dev Agent and Test Optimization How we built an AI SRE agent that investigates like a team of engineers Datadog integrations 2025 recap: Observability for AI, security, and hybrid cloud Design effective executive dashboards with Datadog Implement dbt data quality checks with dbt-expectations Bring faster visibility into AWS Lambda functions with remote instrumentation Troubleshoot faster with the GitLab Source Code integration in Datadog How Cambia Health Solutions saved $30,000 monthly with Cloud Cost Management and the Datadog Resource Catalog Normalize any logs for Cloud SIEM with Datadog's OCSF processor Optimizing Datadog at scale: Cost-efficient observability at Zendesk Detect, diagnose, and resolve network issues easily with CNM Network Health Connect engineering errors to user impact in early-stage products Cilium configuration for Kubernetes operations at scale Designing feedback loops for progressive delivery Ship features faster and safer with Datadog Feature Flags Choosing the right OpenTelemetry Collector distribution Route your monitor alerts with Datadog monitor notification rules Automate Cloud SIEM investigations with Bits AI Security Analyst Cloud threat detection: How to identify risky activity across control and data planes Collecting Kafka performance metrics Monitoring Kafka with Datadog Monitoring Kafka performance metrics
How we migrated a live routing system using AI-assisted refactoring | Datadog
Arnold Wakim · 2026-06-23 · via Datadog | The Monitor blog

When the storage backend for Stream Router hit hard limits, we needed to redesign its data model and migrate it to a new storage architecture without disrupting live production traffic. We would not have completed the implementation in the time frame we had without AI tools.

We used Claude and Cursor to accelerate a systematic, test-driven refactoring process. They weren’t generating code autonomously: For each method, we provided the old implementation, the new schema, and a failing test. The models would generate a first pass, and the tests told us whether it was correct.

We were curious whether AI could help us safely evolve a critical production system. This post is about what worked, what didn’t, and what we learned along the way. We’ll walk through the migration itself, the workflow we used, what gave us confidence in the migration, and where the models were useful versus where they still required human expertise.

Before we get into the migration, it’s worth understanding the system we were changing.

At Datadog, we ingest massive volumes of metrics data every second as part of a platform that processes over a hundred trillion events per day. Routing that data correctly is just as important as ingesting it. Every datapoint then needs to be routed to the right Kafka cluster, topic, and set of partitions so it can be stored and queried correctly, and those routing decisions are constantly changing as our infrastructure evolves. (For a deeper look at the full metrics pipeline, see our overview of the metrics platform.)

Once collected, datapoints are processed and written to Kafka, a durable message broker, before being routed to various storage and query systems. At this scale, Datadog’s internal services need to know exactly which Kafka cluster, topic, and sharding and load-balancing strategy to use for each datapoint. Those answers change constantly as infrastructure evolves.

Stream Router, an internal control plane service at Datadog, provides those answers. It tells producers where to write and queriers where to read, and maintains a history of where data has been at any given point in time. Stream Router does not produce or consume Kafka messages at runtime. Instead, it manages the routing decisions that other services use to configure their own Kafka producers and consumers. At this scale, routing decisions are critical to the health of the metrics pipeline. A bad routing change can have consequences far beyond Stream Router itself.

From config file to control plane

In 2016, routing for the metrics pipeline was managed through a three-line configuration file distributed to every service. As Datadog grew, so did the file—from a couple of lines to thousands. It was edited by hand and rolled out manually. And despite existing safeguards, managing changes became increasingly cumbersome and operationally heavy at scale.

Stream Router replaced that workflow with a centralized gRPC service backed by automated orchestration. Routes were managed through APIs instead of file edits, and rollouts became gradual and automated. 

To support high availability and fault tolerance, Stream Router was designed with an eventually consistent architecture that decouples writes from reads. The write path was backed by FoundationDB using a key-value (KV) model, which fit well with Datadog’s infrastructure and operational model at the time. But as the system grew, that model began to show its limits. The read path relied on RocksDB, serving static snapshots of the write path to high-throughput query traffic.

The following diagram shows this architecture. Administrative changes flow through the write path into the database, which periodically exports snapshots to object storage. On the read side, distributors restore those snapshots into an in-memory database and serve routing queries from there. Producers and queriers never talk to the write path directly.

Stream Router’s architecture separates write and read paths. Routing decisions are written to a database, exported as snapshots to object storage, and restored into in-memory distributors that serve routing queries to producers and queriers.
Stream Router architecture: Write path flows from admin service through database to object storage; distributors serve read queries from memory snapshots.
Stream Router’s architecture separates write and read paths. Routing decisions are written to a database, exported as snapshots to object storage, and restored into in-memory distributors that serve routing queries to producers and queriers.

This design worked for a while, but the storage layer carried a trade-off that the team didn’t fully anticipate. As the routing table grew and operators needed to handle more routes at once, critical operations began hitting FoundationDB’s transaction size limits. The system that had replaced manual configuration was now becoming a bottleneck itself.

When the KV model stopped scaling

To understand why the KV storage hit limits, it helps to look at what Stream Router actually stores.

A route is the core unit of work: It maps a customer’s payload to a specific Kafka stream. But a route doesn’t exist in isolation. It references a sharding strategy, which tells producers how to partition data across that topic. A route is activated by a rule, which controls when and how it takes effect for a given customer.

These entities are inherently relational. Routes reference streams and sharding strategies. Rules reference routes. Business logic validation needs to reason across all of these relationships at once to help ensure consistency before any change takes effect. 

In the KV model, the code had to reconstruct these relationships. It would pull tens of thousands of entries into pod processes and effectively act as a relational database in-process—handling logic that foreign keys would normally enforce in a relational system.

The cost showed up in concrete ways. Some operations hit FoundationDB’s transaction size limits. We first explored the obvious shortcut: swapping FoundationDB for PostgreSQL while keeping the same KV access patterns. That didn’t work either. The most demanding operations were estimated to take 45 minutes, since they still required thousands of sequential round trips to the database. 

The bottleneck came from the data model and the application logic built around it, not the database itself.

We needed a full redesign: a new relational schema and new storage engines. Most importantly, we needed to do it without breaking a system that serves live production traffic to every metrics customer.

Designing a schema that matches the data

Before writing any code or involving AI tools, we redesigned the schema by hand to properly reflect the relationships between domain entities. 

The simplified schema below captures the core structure: Streams and sharding strategies are referenced by routes, which are in turn referenced by rules. Each entity maps directly to the domain concepts introduced earlier, and the foreign key relationships replace what previously had to be reconstructed in application code. (Only primary and foreign keys are shown; each table includes additional columns omitted for clarity.)

Simplified relational schema for Stream Router, where routes reference streams and sharding strategies, and rules reference routes, allowing relationships and constraints to be enforced directly in the database.
Entity relationship diagram of Stream Router schema: Streams and sharding strategies link to routes via foreign keys; routes link to rules.
Simplified relational schema for Stream Router, where routes reference streams and sharding strategies, and rules reference routes, allowing relationships and constraints to be enforced directly in the database.

For the write path, the choice was straightforward. Datadog had been building a self-managed PostgreSQL platform that provided the relational semantics and transaction model we needed, making PostgreSQL a natural fit.

The read path required more thought. The read-serving tier boots from static snapshots and serves queries from memory, so we needed an embeddable database. SQLite was the first candidate, but our schema relies on array columns, which SQLite does not natively support. DuckDB solved both problems: It handles arrays natively and has a SQL dialect that is closely compatible with PostgreSQL. This enabled us to share query logic across both engines rather than maintaining two separate implementations.

This was the human-driven part of the project. Everything that followed—the method-by-method refactoring—was where AI entered the picture.

What made the migration safe

Before we dive into how AI fit into this project, it’s worth stepping back to look at the bigger picture. The migration worked as well as it did because of three pieces that were already in place. These elements enabled us to move quickly without starting from scratch and gave us real trust in the generated code.

First, modular code. At Datadog we strive for modular software, and Stream Router is no exception. Its storage layer sat behind an internal interface we call the Controller. The existing implementation used FoundationDB; building the new one meant writing a second implementation of the same interface against PostgreSQL. The rest of the system didn’t need to change.

Second, a thorough test suite. Given the criticality of what we do, we invest heavily in testable code. Every Controller method was covered by end-to-end tests with clear expectations for what the storage state should look like after each operation. This suite became the binary success criterion for every AI-generated change.

Third, parallel infrastructure. Rémi Calixte, one of our tenured engineers, had built a blue/green deployment architecture—think A/B testing, but for infrastructure. Two fully independent instances of Stream Router run side by side, serving the same requests, and clients target one or the other based on feature flags. A dedicated validator service runs in every cluster, periodically comparing routing responses between the two and alerting the team immediately if anything diverges.

These three pieces—modular interfaces, comprehensive tests, and parallel infrastructure—are what made it safer to hand most of the implementation work to AI.

Mapping the codebase, then implementing method by method

To make AI-assisted refactoring tractable, we needed a way to give the models a clear, human-readable understanding of what the existing system was doing and why.

Phase 1: Building a map

Before any refactoring began, we used Claude to build a structural map of the old codebase. We fed Claude the existing KV controller—a large and deeply nested call stack tightly coupled to the storage layer—and asked it to produce markdown documents describing the intent of each key function. Not what the code did line by line, but why it existed and what behavior it protected.

This turned out to be one of the most valuable steps in the project. In later phases, when we fed these documents alongside the new schema and failing test output, the models had much better context about intent versus implementation, and the back-and-forth per iteration dropped noticeably. 

We saw the same effect with code comments. Adding comments that explained why a piece of logic existed—not just what it did—consistently improved the quality of AI-generated implementations. For anyone attempting a similar migration, it’s worth noting that investing in documentation and comments before handing code to AI pays for itself quickly.

Phase 2: Stub, test, iterate

The core refactoring workflow followed a repeatable loop:

1. Pick a method from the old KV controller.

2. Create a stub in the new PostgreSQL-backed controller that returns an error.

3. Run the end-to-end test suite.

4. Feed the failing test output to Claude or Cursor with context: the old implementation, the new schema, and the markdown documentation from Phase 1.

5. Iterate—sometimes with human input, sometimes not—until the tests pass.

A typical prompt included the failing test output, a description of the expected behavior, and the relevant context from Phase 1. The model would produce a skeleton implementation, which we reviewed and adjusted before running tests again and feeding back any remaining failures.

This worked because of the end-to-end test suite described above. Every test that passed on the KV backend had to pass identically on the relational backend. “Translate this method so these tests pass” is a task AI handles well, and we think the pattern generalizes: Any codebase with a strong test suite can turn a migration into a convergence problem where AI does the iteration and tests do the judging.

What did not work was prompting at a higher level. When we gave the models broader tasks with more context, the results were consistently worse: context overload, hallucinated interfaces, code that compiled but didn’t match the expected behavior. Keeping each prompt scoped to a single method or a specific failing test produced far better results. 

We started sessions frequently as the context window filled up. This is where documenting the purpose of existing code shines: Even with a fresh session, the models could pick up where we left off because the intent was captured outside the conversation.

Phase 3: Blue/green validation in production

The end-to-end test suite gave us confidence in correctness against test fixtures. But Stream Router routes real production traffic, so we needed confidence against real production data. That’s where the blue/green infrastructure came in.

We deployed the PostgreSQL-backed system as “blue” alongside the existing FoundationDB-backed “green.” A validator service compared their responses continuously, every 30 seconds.

Test suites verify behavior against fixtures. The validator service verified behavior against live production data for weeks before we cut over. For a system this critical, that distinction matters.

Where AI fell short

We want to be honest about the limits.

Claude and Cursor did much of the heavy lifting on repetitive work: extracting validation logic, translating method after method from one data model to another, and wiring up the new schema. But when it came to SQL performance, they consistently produced correct queries that were not optimal.

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. We wrote the optimized versions ourselves, and once the models had seen the pattern, they could replicate it in subsequent methods. But they did not discover these patterns independently, even though they exist in the literature.

The takeaway is straightforward: Stay critical of generated code. AI does not automatically recognize all optimization opportunities. Nudging it in the right direction, showing it a well-optimized query, and letting it generalize produced far better results than expecting it to find the optimal path on its own. You can even run EXPLAIN ANALYZE and feed the planner output to the model to spot potentially missing performance optimization opportunities.

Token consumption was also significant, especially early on. We were feeding full test output dumps rather than trimmed excerpts, and the iterative loop of test output, code context, and schema information burned through tokens quickly. We became more disciplined about this over time, but our test suite is verbose by nature and was—at the time—not optimized for AI-assisted workflows.

What changed after the migration

The project went from initial design to production in roughly 3 months (December 2025 through February 2026), with the core proof of concept reached in 4 weeks.

The schema redesign expanded what was possible operationally. Validation that previously required thousands of sequential reads could now be expressed as a single SQL query with joins. Large operations that exceeded transaction size limits on the KV store now complete in one transaction on PostgreSQL with no inherent size ceiling. Business logic that was tightly coupled to the KV abstraction is now decoupled from the storage layer entirely: The controller issues SQL queries, and the storage engine is an implementation detail.

The results were significant:

- Operations that were estimated to run in 45 minutes now complete in ~1 second (nearly 3,000x). API calls that previously timed out now complete in about a second.

- The routing dataset shrank 40x in PostgreSQL, with DuckDB static snapshots even smaller. The KV model required maintaining relationships in application code; PostgreSQL and DuckDB handle that natively.

- Overall latencies decreased by one or more orders of magnitude, from hundreds of milliseconds to a few. PostgreSQL generates efficient query plans and pushes predicates down to the server via WHERE clauses rather than reconstructing relationships in application code only to filter them.

- CPU and memory consumption decreased across pods, both on the read and write paths.

- Database costs decreased by 90% after retiring the managed FoundationDB clusters.

- Deployment to production proceeded without incident.

What we learned from migrating a live system with AI

Stream Router’s migration is a case study in what it takes to deliberately evolve a critical production system. The architecture was human-designed: a relational schema that fits the domain, PostgreSQL and DuckDB chosen for concrete technical reasons, and a blue/green validation strategy that ran for weeks against live data. AI accelerated the implementation: the method-by-method grunt work of translating well-specified behavior from one data model to another. It was not in charge of making design decisions but could be critical when prompted to spot discrepancies. Most importantly, when fed narrow prompts and a set of failing tests, it excelled.

For teams considering AI-assisted refactoring on high-stakes systems, the lesson we offer is this: The quality of your test suite is the ceiling for how much you can trust AI-generated code. Ours made this possible.

The system is faster, cheaper to run, and structurally easier to extend as the metrics pipeline continues to grow. We are already building on top of the new relational foundation, and the ability to iterate on Stream Router’s behavior with confidence is perhaps the most valuable outcome.

If you’re interested in building and evolving large-scale distributed systems, working on data infrastructure, or tackling problems like safe migrations in production, we’re hiring.