Skip to main content
Data Engineering10 min read

AI Migration Agents Can Cut Legacy SQL Debt—If Semantic Context Comes With Them

AI migration agents can dramatically accelerate legacy SQL modernization, as Ecolab and Datafold showed by shrinking 84,000 lines of Snowflake SQL by 6x into documented dbt models. But automation alone is not enough: teams need governed semantic context, validation workflows, and version-controlled transformations to avoid creating a new layer of invisible data debt.

Legacy SQL rarely fails all at once. It accumulates in stored procedures, duplicated business rules, undocumented joins, and “temporary” reporting logic that somehow becomes core infrastructure.

AI migration agents now offer a credible way to accelerate cleanup. But as recent examples from Ecolab, Datafold, AWS, and dbt show, the real modernization opportunity is not just converting old SQL into new SQL—it is turning fragile logic into governed, testable, documented data products.

The Promise and Risk of AI-Assisted SQL Modernization

AI Migration Agents Can Cut Legacy SQL Debt—If Semantic Context Comes With Them
AI Migration Agents Can Cut Legacy SQL Debt—If Semantic Context Comes With Them

For many engineering and data teams, legacy SQL is one of the most expensive forms of technical debt. It is hard to test, hard to review, and hard to change safely. Business logic is often embedded in sprawling queries rather than explicit models. Ownership is unclear. Performance problems are difficult to isolate. And when a key analyst or engineer leaves, the organization loses critical institutional memory.

AI migration agents are changing the economics of this work. Instead of manually reading thousands of lines of procedural SQL or deeply nested transformations, teams can use agents to analyze logic, identify patterns, propose modular replacements, and generate documentation. That can compress months of tedious migration work into a much shorter cycle.

But there is a catch: AI can generate plausible code that is still wrong.

In data engineering, “plausible” is especially dangerous. A query can run successfully, return reasonable-looking numbers, and still misstate revenue, churn, margin, or customer counts. This is why AI-driven modernization must be paired with governed semantic context: shared definitions, lineage, tests, metrics, ownership, and review workflows that make correctness observable.

What Ecolab and Datafold Showed: AI Can Reduce SQL Debt at Scale

A recent dbt Labs case study, “How Ecolab used an AI migration agent to shrink 84,000 lines of legacy SQL by 6x”, offers a practical example of what AI-assisted modernization can look like when applied to real enterprise data debt.

Ecolab partnered with Datafold to rebuild legacy Snowflake logic as clean, documented dbt models. The starting point was significant: 84,000 lines of legacy SQL. Using an AI migration agent, the team reduced that logic by 6x while moving it into a more maintainable dbt structure.

That reduction matters, but not only because the codebase got smaller. The more important modernization gain is that the logic became easier to reason about. Instead of large blocks of opaque SQL, the work was translated into modular models with documentation and structure. That creates a foundation for testing, review, dependency tracking, and future change.

For CTOs and engineering leaders, this is the distinction that matters: the win is not “AI wrote SQL.” The win is that AI helped convert inherited complexity into maintainable architecture.

Why Fewer Lines of SQL Is Not the Whole Story

A 6x reduction in SQL volume is impressive, but line count is only a proxy for maintainability. A shorter query can still be opaque. A generated model can still duplicate business logic. A migration can still preserve bad assumptions from the old system.

The better question is: did modernization make the data platform easier to operate?

A successful migration should improve several dimensions at once:

  • Understandability: Can engineers explain what each model does?
  • Traceability: Can teams see where a metric comes from and what upstream data it depends on?
  • Testability: Are transformations covered by data quality checks, reconciliation tests, and business validations?
  • Change safety: Can teams modify models without breaking downstream reports unexpectedly?
  • Ownership: Is there a clear accountable team or domain owner for each model and metric?

AI migration agents can accelerate the mechanical work, but these operating characteristics come from engineering discipline.

The AWS Revenue Example: Plausible AI Can Be Expensively Wrong

The risk side of the story appears clearly in another dbt Labs article, “Why an AI agent's revenue query was $3.5 million wrong, and how AWS fixed it with dbt Semantic Layer”.

In that example, an AI-generated revenue query looked plausible but produced a result that was $3.5 million wrong. The issue was not that the SQL failed syntactically. It was that the agent lacked the right business context to define revenue correctly.

This is the core lesson for modernization teams: AI does not automatically know your company’s semantics.

Revenue may exclude refunds, include only recognized revenue, depend on contract timing, filter out internal accounts, or apply different logic by region or product line. Similar ambiguity exists for common metrics like active users, booked ARR, net retention, gross margin, incidents, conversion, and utilization.

Without a governed semantic layer, an AI agent may infer definitions from table names, column names, or nearby examples. Sometimes that works. Sometimes it creates a confident answer that contradicts how the business actually operates.

Semantic Context Is the Guardrail

Semantic context gives automation a controlled vocabulary. It tells agents which entities, metrics, dimensions, joins, filters, and business rules are approved. In the AWS example, dbt Semantic Layer helped anchor the AI workflow in governed definitions instead of letting the agent invent its own interpretation.

That pattern is essential for modernization. If you are using AI to migrate legacy SQL, the output should not just be “new queries.” The output should be integrated into a governed data architecture where definitions live in version-controlled code and can be reviewed, tested, and reused.

This is consistent with other recent dbt ecosystem examples. Okta’s work on governing context for AI agents at scale reinforces the need for a single source of truth. Sigma’s large semantic layer on dbt and Dagster shows how semantic definitions can be managed as code across thousands of models. Virgin Media O2’s compute improvements from giving dbt better state awareness show another side of the same principle: modernization works best when platforms have memory, metadata, and structure.

From Refactor Button to Modernization Workflow

The wrong way to use an AI migration agent is to treat it like a magic refactor button: point it at legacy SQL, accept the generated output, and move on. That may reduce visible clutter while preserving or even amplifying hidden risk.

The better approach is to embed AI into a governed migration workflow.

1. Inventory the Legacy Surface Area

Before generating replacements, map what you have. Identify stored procedures, scheduled jobs, dashboard queries, one-off reporting scripts, and manually maintained transformations. Capture runtime frequency, downstream consumers, business owner, and known pain points.

This inventory helps teams prioritize. High-value, high-risk transformations should receive more human review and validation. Low-risk cleanup may be a better fit for faster automation.

2. Extract and Normalize Business Logic

Legacy SQL often contains repeated CASE statements, hardcoded filters, date logic, and inconsistent joins. AI agents can help detect these patterns, but teams should use the migration to normalize business logic into reusable models and metrics.

For example, if five queries define “active customer” differently, the goal should not be to generate five cleaner versions. The goal should be to define “active customer” once, document it, test it, and reference it consistently.

3. Convert to Version-Controlled Models

Ecolab’s move from legacy Snowflake logic into dbt models is important because dbt brings software engineering practices to analytics code. Models can be reviewed in pull requests, tested in CI, documented, versioned, and organized by dependency.

For teams modernizing data systems, this matters as much as the AI itself. Generated code that lives outside version control is just a new maintenance liability. Generated code that enters a disciplined development workflow becomes an accelerant.

4. Validate Against Known Outputs

Every migration needs reconciliation. Compare old and new outputs across representative time periods, customer segments, regions, and edge cases. Do not rely only on row counts or total sums. Validate distributions, null behavior, duplicates, late-arriving data, and exception handling.

For financial or executive metrics, involve business stakeholders. The AWS revenue example shows why: correctness depends on business meaning, not just SQL syntax.

5. Document Assumptions and Ownership

AI-generated migrations should produce or update documentation as part of the workflow. Each model should explain what it does, what assumptions it encodes, where its inputs come from, and who owns it.

This is where modernization pays dividends over time. Future engineers should not have to reverse-engineer migrated code the same way current teams are reverse-engineering legacy SQL.

Practical Implications for Engineering Teams

For developers and platform engineers, AI migration agents are best understood as productivity multipliers, not autonomous maintainers. They can accelerate analysis, translation, documentation, and test generation. But teams still need review boundaries and quality gates.

A practical operating model might look like this:

  • Use AI to summarize legacy SQL and identify transformation intent.
  • Generate candidate dbt models from the legacy logic.
  • Require human review for models tied to financial, compliance, customer, or executive reporting.
  • Attach tests to every migrated model, including uniqueness, freshness, referential integrity, and accepted values where appropriate.
  • Route metrics through a semantic layer rather than letting each agent or analyst redefine them.
  • Use CI/CD to run validation before merge.
  • Monitor production behavior after cutover.

For CTOs, the governance model is just as important as the tooling choice. AI can make migration cheaper, which means organizations may attempt more migrations faster. Without standards, that speed can create a larger mess. With standards, it can finally make long-deferred modernization feasible.

This also has implications for software maintenance strategy beyond data engineering. The same pattern applies to application upgrades, API migrations, infrastructure-as-code cleanup, and dependency modernization. Automation is valuable when it is constrained by context, tests, ownership, and review.

At Vibgrate, we see this as a core principle of sustainable modernization: accelerate the repetitive work, but govern the meaning. The goal is not to replace engineering judgment. The goal is to spend less engineering time deciphering old systems and more time improving them.

What Teams Should Do Next

If your organization is considering AI-assisted SQL migration, start with a pilot that is important enough to matter but bounded enough to validate. Choose a legacy data pipeline with known consumers and measurable outputs. Define success criteria before automation begins.

Good pilot metrics include:

  • Reduction in SQL volume or duplicated logic
  • Number of transformations converted into dbt models
  • Test coverage added
  • Documentation completeness
  • Reconciliation accuracy between old and new outputs
  • Runtime or compute improvements
  • Reduction in support tickets or manual analyst intervention

Most importantly, evaluate whether the migrated system is easier to change safely. Modernization is not complete when the new code runs. It is complete when the next change is less risky than the last one.

Conclusion: AI Can Help Retire Legacy SQL, but Context Makes It Safe

The Ecolab and Datafold example shows that AI migration agents can make a meaningful dent in legacy SQL debt, even at enterprise scale. Shrinking 84,000 lines of Snowflake logic by 6x is a strong signal that automation can accelerate data platform modernization.

The AWS revenue example shows the other half of the story: without governed semantic context, AI can produce results that look right and are materially wrong. A $3.5 million error is not a formatting issue—it is a reminder that business meaning must be explicit.

The path forward is not to avoid AI migration agents. It is to use them inside disciplined modernization workflows: version-controlled models, documented transformations, semantic definitions, validation tests, and accountable ownership. Teams that combine automation with governance will not just migrate faster. They will build data systems that are easier to trust, maintain, and evolve.

Vibgrate CLI

See a real scan run

A replay of the actual CLI running against our test repositories — live progress, real findings, a genuine DriftScore. Nothing executes in your browser.

Replay
demo@vibgrate — bash
❯ npx @vibgrate/cli scan
 
╭──────────────────────────────────────────╮
│ Vibgrate Drift Report │
╰──────────────────────────────────────────╯
 
── node-turborepo (node) .
Runtime: >=18.0.0 (8 majors behind)
Frameworks:
Turbo: 1.13.4 → 2.11.10 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
1 current 1 1-behind 3 2+ behind 1 unknown
 
── @repo/admin (node) apps/admin
Frameworks:
TanStack Query: 5.105.0 → 5.105.0 (current)
React: 18.3.1 → 19.3.1 (1 behind)
React DOM: 18.3.1 → 19.3.1 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vite: 5.4.21 → 8.3.5 (3 behind)
Dependencies:
3 current 9 1-behind 3 2+ behind 4 unknown
 
── @repo/api (node) apps/api
Frameworks:
Express: 4.22.3 → 5.3.0 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vitest: 1.6.1 → 5.0.5 (4 behind)
Dependencies:
7 current 4 1-behind 4 2+ behind 4 unknown
 
── @repo/web (node) apps/web
Frameworks:
Next.js: 14.2.35 → 16.4.3 (2 behind)
React: 18.3.1 → 19.3.1 (1 behind)
React DOM: 18.3.1 → 19.3.1 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
2 current 6 1-behind 3 2+ behind 5 unknown
 
── @repo/config (node) packages/config
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
2 current 2 1-behind 5 2+ behind 0 unknown
 
── @repo/database (node) packages/database
Frameworks:
Prisma: 5.22.0 → 7.10.1 (2 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
1 current 0 1-behind 3 2+ behind 1 unknown
 
── @repo/types (node) packages/types
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
0 current 0 1-behind 1 2+ behind 1 unknown
 
── @repo/ui (node) packages/ui
Frameworks:
React: 18.3.1 → 19.3.1 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
React: 18.3.1 → 19.3.1 (1 behind)
Dependencies:
1 current 4 1-behind 1 2+ behind 1 unknown
 
── @repo/utils (node) packages/utils
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vitest: 1.6.1 → 5.0.5 (4 behind)
Dependencies:
0 current 1 1-behind 2 2+ behind 1 unknown
 
Tech Stack
Frontend: React, React DOM
Meta-frameworks: Next.js
Bundlers: tsx, Turbo, Vite
CSS / UI: Autoprefixer, PostCSS, Tailwind CSS
Backend: Express
ORM / Database: Prisma, Prisma Client
Testing: Vitest
Lint & Format: ESLint, ESLint Prettier, ESLint React, Prettier, typescript-eslint
 
Services & Integrations
Auth: JWT 9.0.3
Databases: Prisma 5.22.0
 
TypeScript
v5.3.3 · strict ✔ · MIXED · target: ES2022
 
Build & Deploy
Package Managers: pnpm
Monorepo: npm-workspaces, pnpm-workspaces, turbo
 
Product Purpose Signals
Frameworks: react, nextjs
Evidence: 177
Top Signals:
- [heading] Dashboard (apps/admin/src/pages/Dashboard.tsx)
- [title] Revenue Overview (apps/admin/src/pages/Dashboard.tsx)
- [copy] workspace:* (packages/ui/package.json)
- [copy] ./dist (packages/ui/tsconfig.json)
- [copy] ./src/index.ts (packages/ui/package.json)
- [copy] @repo/config/tsconfig-base.json (packages/ui/tsconfig.json)
- [copy] @repo/ui (packages/ui/package.json)
- [copy] #3b82f6 (apps/admin/src/pages/Dashboard.tsx)
Unknowns:
- No pricing or billing evidence found.
- No integrations/connectors evidence found.
- No route structure evidence found.
 
Security Posture
Lockfile ✖ · .env ✔ · node_modules ✔
 
Platform
Native modules: turbo
 
Code Quality
Files: 36 · Functions: 183 · Avg complexity: 2.62 · Avg length: 21.13 lines
Max nesting: 2 · Circular deps: 0 · Dead code: 0%
God files: apps/admin/src/pages/Products (448 lines)
 
Database Schema
postgresql · 8 models · 1 enum
Models: Address, CartItem, Category, Order, OrderItem (+3 more)
 
Findings (16 errors, 11 warnings)
✖ @types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.6.6).
vibgrate/dependency-major-lag in .
✖ 60% of dependencies are 2+ major versions behind in node-turborepo.
vibgrate/dependency-rot in .
✖ Node.js runtime ">=18.0.0" reached end-of-life on 2025-04-30 (latest: 26.0.0).
vibgrate/runtime-eol in .
✖ vite is 3 major versions behind (spec: ^5.0.12, latest: 8.3.5).
vibgrate/dependency-major-lag in apps/admin
✖ Vite is 3 major versions behind (current: 5.4.21, latest: 8.3.5).
vibgrate/framework-major-lag in apps/admin
✖ @types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.6.6).
vibgrate/dependency-major-lag in apps/api
✖ vitest is 4 major versions behind (spec: ^1.2.1, latest: 5.0.5).
vibgrate/dependency-major-lag in apps/api
✖ Vitest is 4 major versions behind (current: 1.6.1, latest: 5.0.5).
vibgrate/framework-major-lag in apps/api
✖ @types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.6.6).
vibgrate/dependency-major-lag in apps/web
✖ eslint-plugin-react-hooks is 3 major versions behind (spec: ^4.6.0, latest: 7.1.1).
vibgrate/dependency-major-lag in packages/config
✖ 56% of dependencies are 2+ major versions behind in @repo/config.
vibgrate/dependency-rot in packages/config
✖ 75% of dependencies are 2+ major versions behind in @repo/database.
vibgrate/dependency-rot in packages/database
✖ 100% of dependencies are 2+ major versions behind in @repo/types.
vibgrate/dependency-rot in packages/types
✖ vitest is 4 major versions behind (spec: ^1.2.1, latest: 5.0.5).
vibgrate/dependency-major-lag in packages/utils
✖ 67% of dependencies are 2+ major versions behind in @repo/utils.
vibgrate/dependency-rot in packages/utils
✖ Vitest is 4 major versions behind (current: 1.6.1, latest: 5.0.5).
vibgrate/framework-major-lag in packages/utils
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in .
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/admin
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/api
⚠ Next.js is 2 major versions behind (current: 14.2.35, latest: 16.4.3).
vibgrate/framework-major-lag in apps/web
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/web
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/config
⚠ Prisma is 2 major versions behind (current: 5.22.0, latest: 7.10.1).
vibgrate/framework-major-lag in packages/database
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/database
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/types
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/ui
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/utils
 
╭──────────────────────────────────────────╮
│ Top Priority Actions │
╰──────────────────────────────────────────╯
 
1. Upgrade EOL runtime in node-turborepo
End-of-life runtimes no longer receive security patches and block ecosystem upgrades.
./.
>=18.0.0 → 26.0.0 (8 majors behind)
Impact: −10 drift points (runtime & EOL)
 
2. Fix security posture: no lockfile found
Without a lockfile, installs are non-deterministic. Run the install command to generate one and commit it.
./
Missing: package-lock.json, pnpm-lock.yaml, or yarn.lock
 
3. Upgrade Vitest 1.6.1 → 5.0.5 in @repo/api (+2 more)
4 major versions behind. Major framework drift increases breaking change risk and blocks access to security fixes and performance improvements.
./apps/api
Vitest: 1.6.1 → 5.0.5 (4 majors behind)
./packages/utils
Vitest: 1.6.1 → 5.0.5 (4 majors behind)
./apps/admin
Vite: 5.4.21 → 8.3.5 (3 majors behind)
Impact: −5–15 drift points
 
4. Reduce dependency rot in @repo/types (100% severely outdated)
1 of 1 dependencies are 2+ majors behind. Run `npm outdated` and prioritise packages with known CVEs or breaking API changes.
./packages/types
typescript: 5.9.3 → 7.0.2 (2 majors behind)
Impact: −5–10 drift points
 
5. Reduce dependency rot in @repo/database (75% severely outdated)
3 of 4 dependencies are 2+ majors behind. Run `npm outdated` and prioritise packages with known CVEs or breaking API changes.
./packages/database
@prisma/client: 5.22.0 → 7.10.1 (2 majors behind)
prisma: 5.22.0 → 7.10.1 (2 majors behind)
typescript: 5.9.3 → 7.0.2 (2 majors behind)
Impact: −5–10 drift points
 
╭──────────────────────────────────────────╮
│ Architecture Layers │
╰──────────────────────────────────────────╯
 
Archetype: nextjs (80% confidence)
Files classified: 24 (11 unclassified)
Folders classified: 8
apps/admin/src presentation 100% 4 files
apps/admin/src/pages presentation 100% 2 files
apps/api/src/middleware middleware 100% 2 files
apps/api/src/routes routing 100% 2 files
apps/web/src/app presentation 100% 4 files
apps/web/src/app/products presentation 100% 2 files
apps/web/src/app/products/[id] presentation 100% 1 file
packages/ui/src presentation 100% 6 files
Unclassified source (sample): 11
 
presentation 15 files drift ████████████████████ 100 risk high
routing 4 files drift ████████████████████ 100 risk high
middleware 2 files drift ███████▍░░░░░░░░░░░░ 37 risk moderate
config 2 files drift ░░░░░░░░░░░░░░░░░░░░ 0 risk none
shared 1 file drift ████████████████████ 100 risk high
 
╭──────────────────────────────────────────╮
│ DriftScore Summary │
╰──────────────────────────────────────────╯
 
DriftScore: 70/100
Risk Level: HIGH
Projects: 9
Classified: 8 nano · 1 micro · 0 small · 0 standard
Billable: 0.42 · 9 detected → 0.42 billable projects (micro-project pricing)
0.1 micro · 0.32 nano
These fractions add up across repositories, then round down to whole billable projects.
 
Score Breakdown
Runtime: ████████████████████ 100
Frameworks: ███████████▊░░░░░░░░ 59
Dependencies: ██████▌░░░░░░░░░░░░░ 33
EOL Risk: ████████████████████ 100
 
Scanned at 2026-10-29T14:24:55.610Z · 8.0s · 286 files scanned · 56 workspace files · 27 dirs
❯
Press Run to start.