Knowledge Article

A Risk-Managed Migration from Netezza to Databricks

Lessons from an Agile Netezza to Databricks Program at a Tier 1 Railroad

By Marc-Eric LaRocque, VP, KData July 6, 2026

Every team that owns a Netezza appliance knows the moment is coming. The hardware is aging, workloads keep growing, and leadership is asking why the platform cannot keep pace with the analytics and AI ambitions of the business. Faced with that pressure, most teams reach for a single question: how fast can we convert the code? After delivering a large-scale Netezza migration to Databricks for CN, a Tier 1 North American railroad, our strongest conviction is that this is the wrong question to lead with. Automation moves code. Trust moves the business onto the new platform. The programs that succeed treat the migration as an agile delivery problem built on data the organization can believe in, not as a code translation exercise measured by a compile rate.

Why Netezza migrations stall

The failure modes are remarkably consistent across the industry, and they rarely show up where teams are looking.

The first is treating the work as a pure lift and shift. The appliance quietly absorbed a great deal of behavior over the years: distribution logic, procedural code, and concurrency rules that simply do not exist in the same form on a lakehouse. Teams discover this late, after they have committed to a literal translation, and what was scoped as a shift becomes an accidental re-architecture.

The second is undocumented business logic. The rules that turn raw data into the tables the business actually trusts often live in a few people's heads or in scripts nobody has read in years. The program runs cleanly until it reaches the transformation layer, and then it stops.

The third is leaving validation to the end. When reconciliation is treated as a final gate rather than a continuous discipline, the confidence to cut over never arrives. The technology works, but nobody can prove the new numbers match the old ones, and the program stalls one step short of production.

Everything that follows is the cure for those three patterns.

Best practices that moved the needle

Four practices did the heavy lifting at CN.

Discovery before design. Before any conversion began, we inventoried the tables, pipelines, dependencies, and consumers, and we forced an explicit split between flows that were critical to operations and flows the business was willing to deprecate. This single step is what separates a controlled lift and shift from an unplanned rebuild, because it surfaces hidden complexity while it is still cheap to deal with.

A factory model with defined gates. Dozens of streams cannot move on heroics. We ran the program as a factory, with clear entry and exit criteria for every phase, so each stream cleared the same quality bar in the same way. Consistency, not effort, is what scales.

Automation with judgment held in reserve. A converter does the bulk of the work, and in a typical estimate the large majority of objects fall into the easy and medium buckets. The discipline is to keep human attention for the small tail of complex and very complex objects, where a careless automated conversion does the most damage.

Medallion architecture as the trust mechanism. Bronze mirrors the source exactly. Silver is where mappings, validations, and change data capture live. Gold serves the business. The hardest problems hide in the time dimension and the unique keys, so we resolved what every timestamp meant and which one identified the newest version of a record before we touched silver.

An agile delivery strategy

The instinct to move everything at once is the most expensive instinct in this category of work. We did the opposite.

Workloads were grouped into waves by business domain and complexity, and each wave was delivered through short, repeatable cycles with a fixed lifecycle: convert, compile, data test, reconcile, deploy. A wave that hit trouble was a contained event inside a two week window, not a threat to the whole program. That containment is the entire point of working this way.

The parallel run was our confidence engine. Legacy and Databricks pipelines ran side by side on production data until the results matched exactly or every difference was explained and accepted. We also right sized the depth of testing to the workload rather than applying one standard everywhere. Three depths are worth naming for any team planning its own program: conversion and syntax only, where code simply compiles in Databricks; conversion plus system integration testing, where output is validated against source data through row counts and column and row level checks; and full delivery, where parallel runs on production data and user acceptance precede cutover. The most critical workloads earned the deepest treatment.

None of this works without clear ownership. We agreed on a responsibility split up front. Conversion, unit testing, and integration testing sat with the delivery team. Acceptance, parallel run, and go live decisions sat with the customer. A regular governance cadence kept the program honest, surfacing slippage early instead of at the milestone.

Managing the risks that actually matter

In a Netezza migration the dangerous risks are seldom the ones on the converter dashboard. They are the assumptions hidden in the appliance, the data the business trusts, and the handoffs between teams. We managed an entire register of these, and the most instructive are below. Each one carries the risk, the mitigation we ran, and the fallback when the mitigation was not enough. The full register, with every entry scored and tracked, accompanies this article as a separate working tool. Access the register here for your own use.

Undocumented mappings and business logic. The program ran cleanly into the transformation layer, then risked stalling because the rules behind trusted tables were never written down. We made confirmed mappings a hard entry criterion: silver work on a domain did not begin until its rules were validated by the customer's subject matter experts. When a gap appeared mid wave, we flagged the rework immediately, reprioritized so unblocked domains kept moving, and quarantined the disputed logic rather than guessing at it.

Constructs with no direct equivalent. Procedural code written in NZPLSQL, temporary tables, and column constraints such as UNIQUE and DEFAULT do not exist in the same form on Databricks. A literal conversion either fails or, worse, silently changes behavior. We refactored stored procedures into a combination of SQL and Python notebooks, replaced temporary tables with session scoped temporary views, and rebuilt constraints as explicit validation logic, establishing each pattern once and reusing it across waves. The genuinely hard cases were routed into a manual track so they never gated the automated flow.

Function level behavioral differences. Some code compiles and runs but produces different answers. A documented example is add_months, which handles leap years differently across the two platforms. That kind of difference passes a syntax check and fails a business audit. We maintained a catalog of known differences and added targeted tests for every function on it. When a difference surfaced in a parallel run, we corrected the pattern centrally and re-ran validation rather than patching one job at a time.

Transaction and rollback model differences. Teams assume Netezza concurrency semantics carry over. They do not. Delta defaults to a write serializable isolation level, under which a reader can briefly see a state the table history says never existed, and Netezza's ROLLBACK has no direct equivalent. We set isolation to serializable where concurrency correctness mattered and replaced rollback patterns with Delta versioning for audit and recovery. For the most sensitive pipelines, we ran them single threaded through cutover and lifted concurrency only once results were confirmed.

Data that does not reconcile at cutover. The program can reach go live only to have the business withhold sign off because no one can prove the numbers match. We treated validation as continuous rather than as a final event, running row count, column level, row level, and subset checks every cycle. When variance remained, the contingency was simple and firm: extend the parallel run and hold cutover until the difference was either zero or explained and accepted in writing.

Consumers stranded during transition. Decommissioning a source or cutting a pipeline before every downstream consumer has moved takes a critical report dark. We ran legacy and Databricks pipelines concurrently with temporary data flows so no consumer was ever without a source, and we staged the decommissioning of Netezza only after each consumer was confirmed cut over. The legacy path stayed warm and reversible until the final consumer was verified, which made a rollback a switch rather than a rebuild.

Two further risks deserve a mention even in summary, because they sink programs quietly: environments that arrive late, which we handled by requiring development and integration environments provisioned ahead of the start and routing any delay through formal change control so its schedule impact was visible rather than absorbed; and compute budgets sized against the appliance footprint rather than real access patterns, which we caught by validating budget against actual query behavior in discovery and escalating scope early instead of at the milestone.

The through line across every contingency is the same. The agile, wave based model gives a problem somewhere to live. A risk that surfaces inside a two week wave is a manageable event. The identical risk inside a big bang is a program failure.

The register as a living instrument

Listing risks once at kickoff is theater. The risks above earned their place only because we managed them continuously, and the mechanism for that was a register that stayed alive for the length of the program. It is worth describing how, because the discipline transfers to any migration of this kind.

Every risk carried a likelihood and an impact score, which combined into a severity rating that told leaders where to spend their attention. Every risk had a single named owner, because a risk owned by everyone is owned by no one. And every risk carried two scores rather than one: the inherent score before mitigation, and the residual score after. That second number is the one that matters most, because it answers the only question leadership really has, which is whether the mitigation is actually working or whether the risk is still live.

We reviewed the register on the same cadence as the waves, so a risk that moved was caught in days, not at the milestone. A simple summary view rolled the detail up for steering: how many high severity risks remained, how many had been brought down by mitigation, and what was still open by phase. The register did not remove risk from the program. It made risk visible, owned, and trending in a direction the business could see.

Quality as a first class citizen

In a high volume, governed environment, the thing that lets a program move fast and still earn sign off is quality that is built into the pipeline rather than inspected at the end. This is where our accelerators earned their place. AutoDQ generates and enforces data quality rules inside the pipeline, so trust is continuous and decay is caught the moment it starts rather than when a downstream report breaks. i-QA generates test cases around datasets, which is what allows reconciliation to scale across thousands of objects without a proportional growth in manual effort. Embedded quality is not a luxury at this scale. It is the mechanism that makes confidence repeatable.

The migration is the beginning

It is tempting to treat go live as the finish line. It is closer to the starting line. Once data lands on the lakehouse, the same discipline that delivered the migration unlocks the work that justified it in the first place: unified governance through Unity Catalog, real observability, and the analytics and AI initiatives that the old appliance could never support. The durable lesson from CN is straightforward. Treat a Netezza migration as an agile program anchored in trusted data, manage the real risks deliberately rather than hoping they stay hidden, and the platform change stops being a risk to survive and becomes a capability the business can build on.

Planning a Netezza to Databricks migration?

Let's assess your Netezza environment and define a production path. From discovery through cutover, we bring the patterns that work.

Start a Discussion