A Teradata to Snowflake or Databricks migration has six phases: assess and inventory the estate, build the target foundation, convert code with a vendor tool plus engineering review, load history, run both platforms in parallel with layered reconciliation, then cut over and decommission. Snowflake usually fits SQL- and BI-heavy estates that want a managed warehouse; Databricks fits teams whose roadmap leans on Python, open table formats and machine learning. Either way, the schedule is decided by how well you handle Teradata semantics, data reconciliation and downstream consumers, not by the conversion tool.
Most of it also applies to Oracle Exadata, covered briefly at the end.
Should a Teradata estate move to Snowflake or Databricks?
Both platforms can run a converted Teradata workload. Both support QUALIFY (Snowflake, Databricks) and SQL stored procedures, which are generally available on Databricks from Runtime 17.0. Feature parity rarely settles the decision. These criteria do:
| Criterion | Leans Snowflake | Leans Databricks |
|---|---|---|
| Who writes most of the code | SQL developers and BI teams | Data engineers in Python, Scala or Spark |
| Dominant workload | Scheduled batch ELT, reporting, ad hoc SQL | Mixed batch, streaming, feature engineering, ML |
| Operating model | Few platform engineers, managed service preferred | Platform team comfortable owning compute, jobs and storage layout |
| Storage stance | Managed storage, with Iceberg tables where openness matters | Open formats (Delta, Iceberg) on your own object storage as the default |
| Conversion tooling for Teradata | SnowConvert AI: SQL, procedures, BTEQ, MultiLoad, TPump | Lakebridge: profiler, analyzer, BladeBridge converter, Switch (experimental) |
| AI roadmap | AI used mostly through SQL and BI | Custom model training and serving as a core workload |
If the table does not settle it, look at two things. The first is who will maintain the code in three years: if that team writes SQL, a Spark-first estate becomes a skills problem. The second is what already runs next to Teradata. An existing Databricks ML estate or a Snowflake account used by finance changes the cost of each option more than any benchmark.
What should the assessment inventory before any code is converted?
The assessment answers one question: what must be migrated, and what can be retired. A long-running Teradata system carries objects nobody uses, and each one costs conversion and testing time if it travels.
Inventory these, per subject area:
- Database objects: tables, views, macros, stored procedures, UDFs, join and hash indexes.
- Load and export scripts: BTEQ, FastLoad, MultiLoad, TPump and TPT jobs, with their scheduler definitions.
- Upstream feeds: which source systems load into Teradata, how often and with which change-detection logic.
- Consumers: BI tools, extracts, file feeds to other systems, and applications that query Teradata directly.
- Usage: query logs to see which objects are read, by whom and how often. This lets you retire objects on evidence.
- Security: roles, row-level rules and views used as an access layer.
Lakebridge has a Profiler, which connects to the live system to size workloads (Teradata was added as a profiler source in v0.14.1), and an Analyzer, which reads code files and grades each object from LOW to VERY HIGH complexity (Lakebridge docs). SnowConvert AI marks every construct it cannot translate with an error, warning or issue (EWI) or a functional difference message (FDM) (Snowflake docs), and that count is a good first estimate of manual effort.
The output we recommend is a wave plan by subject area and consumer, with an owner and a retirement list for each wave. Migrating table by table produces a platform where nothing can be switched off until everything is done.
How do you convert Teradata SQL, BTEQ and stored procedures?
The conversion tools, as of late 2026
SnowConvert AI is generally available for Teradata. It converts tables, views, stored procedures, functions, BTEQ, MultiLoad and TPump scripts. BTEQ scripts are rewritten into Snowflake Scripting blocks that wrap each statement in error handling, which emulates .IF ERRORCODE checks (BTEQ reference). It handles both TERA and ANSI session modes, and you should set the mode to match the source before converting.
Lakebridge is the Databricks Labs toolkit built partly on the BladeBridge technology Databricks acquired in February 2025. For Teradata, the transpile guide lists two converters: BladeBridge, a pattern-based converter that outputs Databricks SQL, and Switch, an experimental LLM-based converter that outputs notebooks and incurs model token costs. Morpheus, the AST-based converter, does not cover Teradata at the time of writing.
Treat the conversion rate a tool reports as a starting point. The unconverted remainder usually holds the hardest logic.
The semantics that tools flag but cannot decide for you
These are the differences that let converted code compile and still return different results. Settle them estate-wide, in writing, before the first wave:
- SET tables. In Teradata session mode a table created without
SETorMULTISETdefaults to SET, which does not allow duplicate rows. Snowflake and Databricks tables accept duplicates. SnowConvert flags this asSSC-FDM-TD0024; the fix is deduplication in the load logic, written deliberately. - Case sensitivity. Teradata-mode columns are often
NOT CASESPECIFIC. SnowConvert emulates this withCOLLATEor withUPPER()andRTRIM()(session modes reference). Databricks offers the UTF8_LCASE collation from Runtime 16.1. Note that SnowConvert switches toUPPER()when you target Iceberg tables, because they do not support column-level collation (conversion settings). - Trailing spaces. Teradata ignores trailing pad characters when it compares character strings, which is why SnowConvert’s converted predicates gain
RTRIM(). Joins on paddedCHARkeys are a classic source of missing rows. - PERIOD types. Snowflake has no PERIOD type; SnowConvert maps it to
VARCHARor, optionally, to separate begin and end columns. Choose the two-column form if anyone queries those values. - Numbers without precision. Lakebridge’s BladeBridge maps Teradata
NUMBERwithout precision toDECIMAL(38,18)(release notes). Check that scale against the real data. - Physical design. Primary indexes, compression and journaling options are dropped. The access paths they provided become a clustering, partitioning or warehouse-sizing question that someone has to answer per large table.
Convert procedures, or rebuild them as models?
Many Teradata procedures and BTEQ scripts are transformation pipelines in procedural form: stage, delete, insert, update, log. Converting them one-to-one reaches parity fastest, and it is the right call for logic that will be retired soon or that nobody fully understands yet. For the core warehouse layers we recommend rebuilding the logic as tested, declarative dbt models (see dbt at enterprise scale for how to structure them). A pragmatic split: convert first, reach reconciled parity, then refactor the high-change subject areas wave by wave.
How do you move the data and the history?
Teradata gives you three extraction paths. TPT export runs parallel sessions to files. WRITE_NOS writes query results directly to object storage (Amazon S3, Azure Blob and ADLS, Google Cloud Storage) in Parquet, which keeps the data off intermediate servers. Partitioned SQL extraction over JDBC or ODBC is the fallback.
On the Snowflake side, the SnowConvert AI CLI includes a data migration workflow with an orchestrator and parallel workers that load staged files with COPY INTO, support incremental re-synchronization, and offer regular, tpt and write_nos extraction strategies for Teradata (Teradata setup). It requires hybrid tables in the account. On Databricks, the usual pattern is to land Parquet in your object storage and load it into Delta tables. Lakehouse Federation for Teradata gives read-only, pushed-down queries, useful for validation and interim access but not for bulk transfer.
The sequence that keeps history consistent:
T0 freeze point agreed per wave
|-- bulk history load, partitioned by business date, oldest first
|-- deltas from T0 until cutover (re-runnable, idempotent)
|
upstream feeds re-pointed to land in cloud storage directly
|
source systems --> landing zone (Parquet) --> Snowflake / Databricks
\-> Teradata (legacy loads, frozen at cutover)
Two decisions matter here. If Teradata holds SCD2 history tables, decide whether to migrate them as they are or rebuild history from landed source data. Migrating preserves what users have seen in reports; rebuilding gives you tested history logic that may differ in edge cases. And re-point upstream feeds to the cloud landing zone early, so the new platform stops depending on Teradata as an intermediate hop. That shortens the parallel run and removes a lot of reconciliation noise.
How do you run both platforms in parallel and reconcile?
Reconcile in layers, cheapest first:
- Schema: column names, types, lengths, precision and scale.
- Counts: rows per table and per partition or business date.
- Aggregates: sums, minimums, maximums, distinct and null counts per column.
- Row level: hashes or key-based comparisons on the tables that feed regulated or financial reporting.
- Business output: the top reports and KPIs, compared by the people who own them.
Both vendors automate the first four. Snowflake’s data validation runs schema (L1), metrics (L2) and row (L3) validation with Teradata as a supported source. Lakebridge Reconcile compares schema, row hashes and column values; for Teradata, the row-level reports need a user-installed hash UDF on the source, so plan for a DBA change request early.
Write tolerance rules before the first comparison: floating-point precision, rounding in converted functions, and time zones. For example, Snowflake’s Teradata type mapping drops the offset from TIME WITH TIME ZONE (type mappings). Without agreed tolerances, every difference becomes a meeting. Run the comparison across at least one month-end, and a quarter-end if finance depends on the warehouse, because period-close logic is where converted procedures tend to break.
How do you plan the cutover?
Cut over by wave, and treat each wave as a release with written go/no-go criteria: reconciliation signed off by the data owners, consumers re-pointed and tested, run times within the agreed batch window, and support handed over. On the day, freeze Teradata loads for the wave, apply the final delta, reconcile once more, and switch BI connections and extracts.
Keep the wave’s Teradata objects read-only for an agreed rollback window instead of dropping them. Rolling back is easy when the only thing that changed is where consumers point.
How do you decommission Teradata and keep cloud costs under control?
Work back from the date the Teradata contract or hardware support ends. That date sets the latest cutover for the last wave, and the parallel run, when you pay for both platforms, has to fit before it.
For retention, archive what regulation requires to Parquet in object storage (WRITE_NOS works for this too) and catalog it, rather than keeping a Teradata system alive for occasional lookups.
Set cost controls before the history load, not after the first invoice:
- Snowflake: resource monitors can alert on and suspend warehouses at a credit quota, but they cover warehouses only; serverless features need budgets. Use auto-suspend and separate warehouses per workload so a backfill cannot starve reporting.
- Databricks: budgets send alerts at monthly thresholds and do not stop compute on their own. Tag workloads, attribute serverless usage with usage policies, and query the billable usage system table to report cost per subject area.
The phased plan
| Phase | Goal | Main outputs | Exit criteria |
|---|---|---|---|
| 0. Decide and assess | Target platform and scope | Inventory, usage analysis, retirement list, wave plan | Platform chosen, waves agreed with owners |
| 1. Foundation | A platform you can deploy to safely | Accounts or workspaces, landing zone, security model, CI/CD, cost controls | First pipeline deployed through CI to production |
| 2. Convert and build | Code running on the target, per wave | Converted or rebuilt objects, resolved EWI/FDM list, semantics decisions | Unit and data tests passing |
| 3. History and feeds | Data complete and current | History loaded, deltas running, upstream feeds re-pointed | Counts and aggregates reconciled |
| 4. Parallel run | Proven equivalence | Layered reconciliation reports, tolerance log | Owners sign off, including a month-end |
| 5. Cutover | Consumers on the new platform | Re-pointed BI and extracts, runbook, rollback plan | Go/no-go passed, rollback window open |
| 6. Decommission | Teradata switched off | Archive, closed contracts, retired jobs | No reads on Teradata for the agreed period |
What goes wrong most often
- Converting everything, including objects nobody has queried in a year.
- Reporting the tool’s conversion percentage as project progress.
- Leaving SET-table, case-sensitivity and trailing-space behavior to individual developers, so each wave behaves differently.
- Reconciling row counts only, which misses wrong values in the right number of rows.
- Forgetting file extracts and applications that query Teradata directly, then finding them at cutover.
- Starting the parallel run without tolerance rules or named data owners to sign off.
- Sizing compute for the history backfill and never sizing it back down.
Oracle Exadata: what changes?
The phases apply unchanged. SnowConvert AI is generally available for Oracle, covering tables, views, procedures, functions and packages, and Lakebridge lists Oracle Exadata under its Oracle dialect, converted by BladeBridge and Switch, with Reconcile support. The semantic traps are different. Oracle treats a zero-length string as NULL, so filters and joins on empty strings change meaning. Oracle DATE stores a time component, so mapping it to a date-only type truncates data. PL/SQL packages with package-level variables need an explicit design decision; check how your converter handles them.
Where Duces fits
Our Data & AI practice assesses, designs, builds, deploys and runs data warehouses and data lakes on-prem or in the cloud, including migration to cloud and data migration, with Teradata, Oracle Exadata, Snowflake, Databricks and dbt in the stack. Two of our products cover parts of this playbook. The Data Ingestion Framework lands databases, Salesforce and REST APIs in your own cloud on Google Cloud, AWS or Azure as typed Parquet, with snapshot and incremental loads, which is what re-pointed upstream feeds need. The Data Processing & Transformation Framework is a layered dbt warehouse with SCD2 history, reconciliation tests and UAT views that let testers compare the new warehouse with the existing one, and it runs on Snowflake, Databricks and other dbt-supported warehouses.
If you are weighing a Teradata or Exadata exit, talk to the people who build it.
Frequently asked questions
Should we migrate Teradata to Snowflake or to Databricks?
Choose Snowflake when the estate is mostly SQL, BI and scheduled batch, and the team wants a managed warehouse with little platform engineering. Choose Databricks when Python and Spark engineering, open table formats, streaming or machine learning are a large part of the roadmap. Both can run a converted Teradata workload; the deciding factors are your users, skills and operating model rather than SQL feature parity.
Which tools convert Teradata code automatically?
Snowflake offers SnowConvert AI, which converts Teradata DDL, DML, stored procedures, functions, BTEQ, MultiLoad and TPump scripts and flags what it could not translate. Databricks offers Lakebridge, a Databricks Labs toolkit with a profiler, a code analyzer, the BladeBridge converter for Teradata and an experimental LLM-based converter called Switch. Neither removes the need for engineers to review the output and resolve the flagged items.
How do Snowflake and Databricks handle Teradata SET tables and case-insensitive columns?
Neither platform rejects duplicate rows the way a Teradata SET table does, so deduplication has to move into the load logic. Case-insensitive comparisons are emulated with collations or UPPER() in Snowflake, and with the UTF8_LCASE collation in Databricks. Decide these rules once for the whole estate and test them, because conversion tools only flag them.
How do you prove the migrated data matches Teradata?
Reconcile in layers: schema, row counts, column aggregates such as sums, minimums, maximums and null counts, then row-level hashes on the tables that matter most, and finally the business reports themselves. Snowflake's SnowConvert AI data validation and Databricks Lakebridge Reconcile both support Teradata as a source. Run the comparison across at least one month-end so period-close logic is exercised.
Does the same approach work for Oracle Exadata?
Yes. The phases are the same and both vendors support Oracle as a source: SnowConvert AI converts Oracle tables, views, procedures, functions and packages, and Lakebridge lists Oracle Exadata as an Oracle dialect source. The semantic traps differ: Oracle treats empty strings as NULL and its DATE type carries a time component.
Sources
- docs.snowflake.com/en/migrations/snowconvert-docs/general/about
- docs.snowflake.com/en/migrations/snowconvert-docs/general/getting-started/running-snowconvert/supported-languages/teradata
- docs.snowflake.com/en/migrations/snowconvert-docs/translation-references/teradata/scripts-to-snowflake-sql-translation-reference/bteq
- docs.snowflake.com/en/migrations/snowconvert-docs/general/getting-started/running-snowconvert/conversion/teradata-conversion-settings
- docs.snowflake.com/en/migrations/aim-for-datawarehouses/code-conversion/translation-references/teradata/session-modes
- docs.snowflake.com/en/migrations/aim-for-datawarehouses/manual-migration/data-migration
- docs.snowflake.com/en/migrations/aim-for-datawarehouses/data-migration-validation/migrate-teradata
- docs.snowflake.com/en/migrations/aim-for-datawarehouses/data-migration-validation/data-validation
- docs.snowflake.com/en/user-guide/resource-monitors
- docs.snowflake.com/en/sql-reference/constructs/qualify
- docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-qry-select-qualify
- databrickslabs.github.io/lakebridge/docs/overview
- databrickslabs.github.io/lakebridge/docs/choosing_tools
- databrickslabs.github.io/lakebridge/docs/transpile
- databrickslabs.github.io/lakebridge/docs/reconcile
- github.com/databrickslabs/lakebridge/releases
- databricks.com/company/newsroom/press-releases/databricks-acquires-bladebridge-technology-and-talent
- databricks.com/blog/introducing-sql-stored-procedures-databricks
- docs.databricks.com/aws/en/sql/language-manual/sql-ref-collation
- docs.databricks.com/aws/en/query-federation/teradata
- docs.databricks.com/aws/en/admin/account-settings/budgets
- docs.databricks.com/aws/en/admin/system-tables/billing
- docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Native-Object-Store-Getting-Started-Guide/Writing-Data-to-External-Object-Store/WRITE_NOS
- docs.teradata.com/r/Lake-Working-with-SQL/SQL-Reference/SQL-Fundamentals/Database-Objects/Tables/Duplicate-Rows-in-Tables
- docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/Nulls.html
- docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Data-Types.html