Hi Databricks Community,
I’d like to hear how other Data Engineers are handling schema evolution with Auto Loader in production environments.
Consider the following scenario:
We have a continuously running ingestion pipeline using Auto Loader that processes JSON files into a Bronze Delta table.
df = (
spark.readStream
.format("cloudFiles")
.option("cloudFiles.format", "json")
.option("cloudFiles.schemaLocation", schema_path)
.option("cloudFiles.schemaEvolutionMode", "addNewColumns")
.load(source_path)
)
Everything works as expected until the source system introduces a new column.
With addNewColumns, Auto Loader detects the new field and updates the schema, but the stream can stop with an UnknownFieldException before continuing after a restart.
For a production pipeline, I see a few possible approaches:
- Keep addNewColumns and configure the Lakeflow Job to restart automatically.
- Use rescue mode and capture unexpected fields in _rescued_data.
- Use schema hints for fields that we expect could change.
- Use addNewColumnsWithTypeWidening where supported when compatible data type changes are also expected.
My main question is:
What approach do you consider the best practice for production pipelines where upstream schemas can change frequently?
I’m particularly interested in how you balance:
• Pipeline availability
• Automatic schema evolution
• Data quality
• Avoiding silent schema changes
• Governance with Unity Catalog
• Operational maintenance
Would you allow schema evolution automatically in the Bronze layer and enforce a stricter schema in Silver, or would you enforce the schema from the ingestion layer?
Interested to hear how others are designing this in real-world Databricks architectures.
#Databricks #DataEngineering #AutoLoader #StructuredStreaming #Lakeflow #DeltaLake #UnityCatalog