More Software Engineering Radio episodes

Sahil Walia on Schema Changes and Data Migrations thumbnail

Sahil Walia on Schema Changes and Data Migrations

Published 7 Oct 2026

Recommended: Schema as source of truth

Duration: 47:02

"Schemas define data structure, apply across systems, and require careful evolution to avoid breaking changes, with best practices including additive updates, blue-green deployments, and stable identifiers."

Episode Description

Shail Walia, a senior technical architect at Snowflake, joins host Robert Blumen for a conversation about schema migration and data migration. Togethe...

Overview

A schema serves as a blueprint defining the structure of data, including fields, types, and constraints, ensuring consistency across systems. It applies broadly beyond databases to any data exchange, such as APIs, files (e.g., Parquet), or service boundaries. While a schema defines data shape, an API includes behaviors and operations, though some - like GraphQL - combine both. Schema enforcement varies: schema-on-write systems (e.g., OLTP) validate at write time, while schema-on-read systems (e.g., NoSQL) defer validation, making so-called "schema-less" databases more accurately described as schema-flexible. Examples include CLI tools relying on response schemas and CI/CD pipelines depending on structured logs.

Schema evolution is driven by business needs, regulatory changes, or technical requirements, with additive changes (e.g., nullable columns) being safer than breaking ones (e.g., dropping fields). Schema evolution differs from data migration - changes like adding a nullable column may not require migration, but altering types or adding non-nullable fields do. Migrations pose challenges including performance impact, data consistency, and downtime, especially at scale. Safe practices include blue-green deployments, replication, and using stable identifiers (e.g., field IDs in Avro, Protobuf, or Iceberg) to decouple identity from names. Technologies like Apache Iceberg enhance safety through metadata-rich formats, columnar storage efficiency, and immutable field IDs that prevent corruption during schema changes.

Effective schema management requires planning, versioning tools (e.g., Flyway, Snowflake's Schema Change), and migration strategies like double writes, read repair, or logical replication to minimize disruption. Additive changes are common and low-risk, while structural changes demand coordination and impact analysis. Architectural best practices emphasize backward compatibility, stable identifiers, and minimizing unnecessary changes. Real-world cases, such as migrating from Hive to Iceberg, highlight risks of position-based schema mapping versus ID-based approaches. Ultimately, successful schema evolution balances agility with reliability, treating schema changes as controlled, testable processes integrated into development workflows.

What If

  • What if you enforced schema-on-write for your API responses before launching your next feature?

    • Move: Define a strict JSON schema for all API outputs using a tool like JSON Schema or Zod, and integrate validation in your backend response pipeline.
    • Why Now?: Catch breaking changes early in development - before frontend or third-party integrations consume malformed data - reducing debugging time and production incidents.
    • Expected Upside: Fewer integration bugs, improved trust from consumers, and smoother versioning when evolving APIs; sets foundation for automated contract testing.
  • What if you migrated your database schema changes through versioned scripts instead of ad-hoc ALTER statements?

    • Move: Adopt Flyway or a similar migration tool to manage schema changes as incremental, version-controlled SQL scripts with up/down capabilities.
    • Why Now?: Prevent untracked, risky ALTER TABLE operations on production - especially on large tables - by introducing safe, repeatable, and reviewable change workflows.
    • Expected Upside: Eliminate downtime from uncoordinated schema locks, enable rollback during failures, and create auditability for compliance and team collaboration.
  • What if you used stable field IDs instead of column names to decouple schema evolution from data consumption?

    • Move: Implement field identifiers (e.g., via Protobuf field numbers or Iceberg-style column IDs) in your data layer, and reference them in downstream logic instead of names.
    • Why Now?: Avoid breaking reports or pipelines when renaming or reordering columns - common in agile environments - while enabling safer refactoring.
    • Expected Upside: Enable non-breaking schema evolution (e.g., rename user_name username) without coordinated deploys, reducing deployment friction and increasing iteration speed.

Takeaway

  • Implement additive schema changes (e.g., adding nullable columns) by default to ensure backward compatibility and avoid breaking downstream consumers.
  • Use schema validation tools (e.g., schema registries, CI/CD linting) to detect breaking changes early and enforce compatibility checks before deployment.
  • Adopt stable field identifiers (e.g., numeric field IDs as in Avro or Iceberg) instead of relying on column names to safely evolve schemas without disrupting data consumers.
  • For large-scale migrations, apply zero-downtime techniques such as logical replication (e.g., using Postgres WAL) or double writes to minimize service disruption and maintain data consistency.
  • Treat schema migrations as versioned code changes using tools like Flyway or Snowflake's Schema Change, enabling auditability, rollback, and iterative deployment in alignment with Agile workflows.

Final Notes

A schema acts as a formal blueprint for data structure (fields, types, rules) and applies wherever structured data crosses system boundaries.

Distinguish schema from API: schema defines the shape of data, while API defines operations and behaviors, though some systems like GraphQL combine them.

Schema flexibility operates on a spectrum from strict schema-on-write to flexible schema-on-read. Shifting validation earlier improves overall data reliability.

Additive changes like adding a nullable column are safe and typically do not require data migration. Structural changes like type conversions or column splits usually do.

Dropping a column, renaming a field, or making an optional field required are breaking changes. These require explicit coordination with downstream consumers to prevent failures.

Maximize backward-compatible, additive schema changes. This keeps most evolution in the safe category and minimizes disruption to writers and readers.

Use stable identifiers such as field numbers in Avro/Protobuf or column IDs in Iceberg. This decouples column identity from its name or position, preventing corruption during renames.

Treat schema evolution in Iceberg as metadata operations rather than full data rewrites. This allows adding, renaming, and reordering columns safely and efficiently.

Avoid position-based schema mapping where columns are identified by ordinal position. This approach silently corrupts data when the column order changes during evolution.

Plan for specific operational risks during migration: database locking, throughput limits on large datasets, and consistency during live writes. Use strategies like logical replication or double writes to achieve zero-downtime migrations.

Version control all schema changes using dedicated tools (e.g., Flyway, Schemachange). Combine this with CI validation and schema registries to catch breaking changes before deployment.

Assess the blast radius of every schema change before proceeding. High-impact fields requiring strict coordination demand different handling than low-usage fields with flexible timelines.

Treat high-cost migrations with strict rollback schedules and thorough testing in staging environments that mirror production data volumes.

Unplanned or silent schema changes erode trust in data systems. Aim for deterministic data delivery where evolution is anticipated, validated, and backward-compatible.

Recent Episodes of Software Engineering Radio

29 Oct 2026 Danilo Krummrich on Rust in the Linux Kernel

"Nova GPU driver project integrates Rust into the Linux kernel to replace the aging Novo driver, leveraging Rust's memory safety for better reliability and performance while addressing firmware and architectural challenges through incremental, collaborative updates."

30 Sept 2026 Raju Dandigam on Building Production AI Agents

"Explores production AI agents, their autonomy, safety, and engineering best practices, comparing workflows, tool design, orchestration, and memory systems while addressing challenges like cost, latency, and reliability."

16 Sept 2026 Milan Milanovic on the Laws of Software Engineering

"Explores key software engineering principles (like Conway's Law, Brooks' Law) and their impact on systems, teams, and decision-making, emphasizing context-dependent trade-offs, AI's role, and practical applications like measuring technical debt."

9 Sept 2026 Owen McGirr on Software Accessibility

"Accessibility in software development must be prioritized from the start, integrating inclusive design practices like multiple input methods, proper labeling, and user testing to benefit all users, not just those with disabilities."

3 Sept 2026 Sahil Walia on Apache Iceberg

"Apache Iceberg is a scalable, interoperable data framework that unifies OLTP and OLAP workloads, separates storage and compute, and enables efficient metadata-driven operations, governance, and cost savings across industries."

More Software Engineering Radio episodes