Google automates dual-write database migration to Spanner
Mon, 7th Sep 2026 (Today)
Google's Finance Engineering team has built an automated refactoring pipeline to support a database migration to Spanner. The system uses Antigravity CLI in headless mode to update data access code across more than 30 DAOs.
The work addresses a common problem in large database migrations: how to move a production service to a new datastore without taking systems offline. In this case, the team needed both its legacy datastore and Spanner to receive the same writes during the migration period while engineers verified that data remained identical in both systems.
That meant changing each DAO so it could write to two databases at once and, during part of the process, read from both as well. The team also had to backfill historical records into Spanner, then verify through automated checks that writes matched byte for byte across the two stores.
At the scale of Google's internal finance systems, the engineering effort was substantial. Each DAO needed a separate mutation conversion layer to map domain models to Spanner tables, dual-write handling and rollback or error-reporting logic, and unit tests using fake time sources and test doubles.
Doing that work manually across 30 or more DAOs would have taken months, the engineers said. Instead, they standardised the migration pattern around a decoupled MutationConverter interface that isolates Spanner schema translation from core business logic.
Standard pattern
Under that approach, schema mapping moved into dedicated converter units rather than being embedded directly in DAO logic. That gave the automation system a fixed target structure for generating refactored code and associated tests.
A script called migration_ui.py drives the pipeline and runs Antigravity CLI in headless mode. The script takes a DAO name, gathers the existing single-write source code and schema, and submits them together with the team's structural rules and prompt templates.
Antigravity then generates three main outputs: a new converter, a refactored dual-write DAO, and unit tests. After code generation, the script runs the test suite and, if linting or test failures appear, feeds those error logs back into the tool for another correction pass.
The process can run unattended, letting engineers queue several DAOs for migration at once. That made it possible to submit batches of work overnight and return to validated changelists ready for human review.
Why automation
The engineers distinguished between interactive coding tools inside integrated development environments and scripted command-line workflows. They said chat-style tools may suit exploratory tasks but are less useful for repeatable, multi-file refactoring across a large codebase where consistency matters.
To address that, the Finance Engineering team treated prompts as version-controlled engineering artefacts. It built reusable prompt templates covering issues such as timestamp serialisation, nullability conversions, mutation ambiguity, and FakeTimeSource test injection.
That matters because dual-write migrations carry operational risk, particularly in financial systems where accuracy must be maintained throughout the transition period. A simple cutover was not suitable for the service in question, so the migration had to be broken into a historical backfill phase, a dual-write and dual-read phase, and then a verification phase.
According to the team, the automated method reduced the repetitive coding and testing required for each DAO. It also aimed to improve consistency because every generated DAO followed the same MutationConverter pattern and underwent automated unit testing.
Google framed the project as an example of combining a distributed database with code-generation tooling to manage internal software change. The database migration itself formed part of a wider effort to modernise a legacy data layer in its finance engineering stack.
Internal lessons
The team also set out three practical lessons from the project. First, engineers should decouple schema translation early by defining a strict interface between the application's business logic and the target database SDK.
Second, teams carrying out repetitive refactoring across more than a handful of files should move from interactive AI tools to headless automation. In the team's view, scripted workflows make it easier to enforce consistency and connect generation directly to testing.
Third, build and test systems should act as the guardrail for code generation. By tying the generation loop to automated tests, the team could catch compile and assertion failures before code reached a developer for review.
The result, according to Google's engineers, was that DAO dual-write migrations that would once have required extensive manual work could be completed much faster while preserving strict data parity in staging environments.