Skip to content
Reliable Data Engineering
Practice problem hard migrationsql-translationllmagentsvalidation
Practise with timer, notes and rubric

Design a Legacy Warehouse to Lakehouse Migration

Problem

An enterprise runs a legacy MPP warehouse (Teradata/Exasol/Oracle/Netezza) with ~3,000 SQL objects (views, procedures, scripts), 400 ETL jobs and 500 dashboards. It must move to a lakehouse (Spark SQL/dbt) within 18 months without breaking reports. Manual conversion is estimated at 20,000 engineer-hours. Design the migration approach and the tooling, including automated SQL translation.


Clarifying questions

QuestionAssumed answer
Can the old and new systems run in parallel?Yes, for up to 6 months per domain
Data sources?The same upstream systems feed the legacy DWH; we can tap them directly
SQL complexity?60% simple views, 30% medium (window functions, dialect functions), 10% complex procedural scripts (loops, temp tables, dynamic SQL)
Acceptance criteria?Business-signed reconciliation: results equal within defined tolerances
AI usage allowed?Yes, with an enterprise LLM endpoint; no data leaves the tenant

1. Strategy first, tools second

flowchart LR
    A[1 · Assess<br/>inventory, lineage, usage] --> B[2 · Prioritise<br/>by value and dependency]
    B --> C[3 · Land data<br/>bronze from sources]
    C --> D[4 · Convert code<br/>automated + reviewed]
    D --> E[5 · Validate<br/>reconcile in parallel run]
    E --> F[6 · Cut over<br/>per data product]
    F --> G[7 · Decommission<br/>legacy objects]
    G -.->|next wave| B

2. Architecture of the conversion factory

flowchart TB
    SRC[(Legacy SQL repo<br/>+ query logs)] --> PARSE[Parser / classifier<br/>sqlglot AST, complexity score]
    PARSE --> RULE[Deterministic transpiler<br/>dialect rules: functions, types, syntax]
    RULE --> CHECK1{Compiles on target?<br/>EXPLAIN / dry run}
    CHECK1 -->|yes| VAL
    CHECK1 -->|no or complex| AGENT
    subgraph AGENT["LLM conversion agent"]
        RET[Retrieve similar solved examples<br/>RAG over migration knowledge base] --> GEN[Generate target SQL]
        GEN --> CMP[Compile check]
        CMP -->|error| REP[Repair with error message<br/>max N attempts]
        REP --> GEN
    end
    AGENT --> VAL[Validation harness<br/>run both on sample data,<br/>compare result sets]
    VAL -->|match| PR[Pull request: dbt model<br/>+ generated tests]
    VAL -->|mismatch / low confidence| HUM[Human review queue]
    HUM --> KB[(Knowledge base:<br/>patterns, fixes, examples)]
    PR --> KB
    KB --> RET

2.1 Deterministic first, LLM second

2.2 Validation is the product

LLM output is a proposal. Trust comes from validation:

  1. Compile/EXPLAIN on the target (syntax, types, object resolution).
  2. Result equivalence on representative data: run legacy and converted queries on the same snapshot, compare row counts, column-level checksums/aggregates, and row-level diffs on keys (with tolerance for float rounding, timestamp precision, NULL ordering, collation differences).
  3. Generated tests (unique/not_null on keys, accepted values) added to the dbt model.
  4. Confidence score = f(path taken, repair attempts, validation coverage) → routes to auto-merge-candidate vs human review.

2.3 Classic dialect traps (good interview material)

TrapExample
NULL semantics in string concat`‘a’
Integer division5/2 = 2 in some engines, 2.5 in Spark SQL
Implicit castsString-to-date comparisons accepted silently in one dialect, errors in another
Date functionsADD_MONTHS, week numbering (ISO vs US), timezone handling
Sorting and collationCase sensitivity, NULLS FIRST/LAST defaults
QUALIFY, TOP, ROWNUMSyntax differences
Procedural codeCursors/loops → set-based SQL or orchestrated dbt models
Temp tables / transactionsMap to CTEs, temp views, or intermediate models

3. Data migration and parallel run

4. Program management signals (senior/staff)

5. Trade-offs

DecisionChoiceAlternative
ConversionRules first, LLM agent for the long tail, humans for low confidenceFully manual (slow), LLM-only (inconsistent, hard to trust)
Source of new pipelinesOriginal sources via CDCCopy from legacy DWH (fast, inherits debt, keeps legacy alive)
RedesignMinimal during migration, optimise afterFull redesign (risk, timeline)
ValidationAutomated result-set comparisonSpot checks (misses edge cases)

6. What separates a senior answer

7. Follow-up questions

How do you measure whether the AI conversion is actually saving time?

Baseline manual hours per object by complexity class (from a pilot). Track, per object: path (rules / agent / human), repair attempts, review time, defects found later. Report auto-validated rate and human-hours per object by class over time; the knowledge base should drive the curve down.

Result sets differ by 0.01% on a revenue view. Ship it?

Investigate first: usually rounding (decimal precision/scale, float), timezone/date boundary, NULL handling or duplicate rows from a join difference. Agree tolerances with the business beforehand; financial outputs typically require exact equality at the reported precision. Document known, accepted differences.


Self-assessment rubric