<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram in Community Articles</title>
    <link>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163206#M1364</link>
    <description>&lt;H2&gt;Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram&lt;/H2&gt;&lt;P&gt;Every Lakehouse conversation eventually shows the same three boxes: Bronze, Silver, Gold. It's a great mental model — but on a real enterprise migration, the diagram is the easy part. The decisions that actually determine whether the architecture holds up are the ones that never make it onto the slide.&lt;/P&gt;&lt;P&gt;I recently worked on a migration of a large enterprise analytics estate — legacy MPP warehouse (Greenplum) plus a brittle Talend ETL stack — onto a Databricks Lakehouse on AWS. Here are the four decisions that mattered most, written up in case they save someone else a design cycle.&lt;/P&gt;&lt;H3&gt;1. Bronze must stay "boringly faithful" — resist the urge to clean early&lt;/H3&gt;&lt;P&gt;The biggest temptation on any migration is to fix obviously bad data on the way into Bronze. Don't. If Bronze applies any business logic, you've coupled your raw layer to a specific interpretation of correctness — and the moment that interpretation changes (it will), you have no clean copy to reprocess from.&lt;/P&gt;&lt;P&gt;What we standardized on:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Source structure preserved as-is, no type coercion, no filtering&lt;/LI&gt;&lt;LI&gt;Four audit/lineage columns bolted on top: _source_system, _ingested_at, _batch_id, _file_name&lt;/LI&gt;&lt;LI&gt;Schema evolution enabled (mergeSchema) so upstream column changes don't break the load&lt;/LI&gt;&lt;/UL&gt;&lt;PRE&gt;(spark.readStream
  .format("cloudFiles")
  .option("cloudFiles.format", "parquet")
  .option("cloudFiles.schemaEvolutionMode", "addNewColumns")
  .option("cloudFiles.schemaLocation", schema_path)
  .load(landing_path)
  .withColumn("_source_system", lit(source_name))
  .withColumn("_ingested_at", current_timestamp())
  .withColumn("_batch_id", lit(batch_id))
  .writeStream
  .option("checkpointLocation", checkpoint_path)
  .trigger(availableNow=True)
  .toTable("bronze.raw_table"))&lt;/PRE&gt;&lt;P&gt;The payoff: when a downstream bug is discovered in Silver logic three weeks later, you replay Bronze and reprocess — you don't re-extract from a source system that may have already moved on.&lt;/P&gt;&lt;H3&gt;2. Gold is a governance boundary, not a storage boundary&lt;/H3&gt;&lt;P&gt;This is the one that surprises people. "Gold" doesn't have to mean "physically materialized table." On this project, most of Gold was implemented as &lt;STRONG&gt;governed views over Silver&lt;/STRONG&gt;, not copies:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;No physical duplication → no second copy to keep in sync, no extra storage cost&lt;/LI&gt;&lt;LI&gt;Always reflects the latest Silver state&lt;/LI&gt;&lt;LI&gt;Simpler to govern — one copy of the data, one set of grants&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;We only materialized a Gold table (with OPTIMIZE/ZORDER applied) when a specific consumer had a concurrency or latency SLA that a view genuinely couldn't meet. That was the exception, not the default.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;The decision rule we used:&lt;/STRONG&gt; default to a curated view; materialize only when you can point to a measured concurrency/latency requirement that justifies the extra storage and refresh complexity.&lt;/P&gt;&lt;H3&gt;3. Silver is where the real engineering effort lives — and MERGE is the mechanism&lt;/H3&gt;&lt;P&gt;Bronze is fidelity. Gold is a contract. Silver is where you actually earn your keep:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Standardize types and naming&lt;/LI&gt;&lt;LI&gt;Deduplicate on natural/business keys&lt;/LI&gt;&lt;LI&gt;Enforce data quality rules (nulls, referential integrity, ranges)&lt;/LI&gt;&lt;LI&gt;Join and enrich against reference/dimension data&lt;/LI&gt;&lt;LI&gt;Apply domain-specific business rules&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;The mechanism that makes all of this idempotent is Delta's MERGE:&lt;/P&gt;&lt;PRE&gt;MERGE INTO silver.entity_table AS target
USING staged_updates AS source
ON target.business_key = source.business_key
   AND target.effective_date = source.effective_date
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *&lt;/PRE&gt;&lt;P&gt;One subtlety worth calling out: if your domain has legitimately repeating keys (e.g., effective-dated HR or reference data), your dedup/merge key &lt;STRONG&gt;must&lt;/STRONG&gt; include the version/effective-date column. Keying only on the natural identifier will silently collapse valid history into a single row — a bug that's easy to introduce and painful to find after the fact.&lt;/P&gt;&lt;H3&gt;Takeaways&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;Keep Bronze dumb and durable; put correctness in Silver where it can be revised&lt;/LI&gt;&lt;LI&gt;Don't assume Gold means "another copy" — default to views, materialize only with a measured reason&lt;/LI&gt;&lt;LI&gt;MERGE-based up-serts are what make reprocessing safe; get your key design right, especially for versioned/effective-dated data&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Curious how others have handled the Gold view-vs-table decision on their own Lakehouse migrations — would love to compare notes in the replies.&lt;/P&gt;</description>
    <pubDate>Thu, 16 Jul 2026 15:43:26 GMT</pubDate>
    <dc:creator>TriambakR</dc:creator>
    <dc:date>2026-07-16T15:43:26Z</dc:date>
    <item>
      <title>Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram</title>
      <link>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163206#M1364</link>
      <description>&lt;H2&gt;Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram&lt;/H2&gt;&lt;P&gt;Every Lakehouse conversation eventually shows the same three boxes: Bronze, Silver, Gold. It's a great mental model — but on a real enterprise migration, the diagram is the easy part. The decisions that actually determine whether the architecture holds up are the ones that never make it onto the slide.&lt;/P&gt;&lt;P&gt;I recently worked on a migration of a large enterprise analytics estate — legacy MPP warehouse (Greenplum) plus a brittle Talend ETL stack — onto a Databricks Lakehouse on AWS. Here are the four decisions that mattered most, written up in case they save someone else a design cycle.&lt;/P&gt;&lt;H3&gt;1. Bronze must stay "boringly faithful" — resist the urge to clean early&lt;/H3&gt;&lt;P&gt;The biggest temptation on any migration is to fix obviously bad data on the way into Bronze. Don't. If Bronze applies any business logic, you've coupled your raw layer to a specific interpretation of correctness — and the moment that interpretation changes (it will), you have no clean copy to reprocess from.&lt;/P&gt;&lt;P&gt;What we standardized on:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Source structure preserved as-is, no type coercion, no filtering&lt;/LI&gt;&lt;LI&gt;Four audit/lineage columns bolted on top: _source_system, _ingested_at, _batch_id, _file_name&lt;/LI&gt;&lt;LI&gt;Schema evolution enabled (mergeSchema) so upstream column changes don't break the load&lt;/LI&gt;&lt;/UL&gt;&lt;PRE&gt;(spark.readStream
  .format("cloudFiles")
  .option("cloudFiles.format", "parquet")
  .option("cloudFiles.schemaEvolutionMode", "addNewColumns")
  .option("cloudFiles.schemaLocation", schema_path)
  .load(landing_path)
  .withColumn("_source_system", lit(source_name))
  .withColumn("_ingested_at", current_timestamp())
  .withColumn("_batch_id", lit(batch_id))
  .writeStream
  .option("checkpointLocation", checkpoint_path)
  .trigger(availableNow=True)
  .toTable("bronze.raw_table"))&lt;/PRE&gt;&lt;P&gt;The payoff: when a downstream bug is discovered in Silver logic three weeks later, you replay Bronze and reprocess — you don't re-extract from a source system that may have already moved on.&lt;/P&gt;&lt;H3&gt;2. Gold is a governance boundary, not a storage boundary&lt;/H3&gt;&lt;P&gt;This is the one that surprises people. "Gold" doesn't have to mean "physically materialized table." On this project, most of Gold was implemented as &lt;STRONG&gt;governed views over Silver&lt;/STRONG&gt;, not copies:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;No physical duplication → no second copy to keep in sync, no extra storage cost&lt;/LI&gt;&lt;LI&gt;Always reflects the latest Silver state&lt;/LI&gt;&lt;LI&gt;Simpler to govern — one copy of the data, one set of grants&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;We only materialized a Gold table (with OPTIMIZE/ZORDER applied) when a specific consumer had a concurrency or latency SLA that a view genuinely couldn't meet. That was the exception, not the default.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;The decision rule we used:&lt;/STRONG&gt; default to a curated view; materialize only when you can point to a measured concurrency/latency requirement that justifies the extra storage and refresh complexity.&lt;/P&gt;&lt;H3&gt;3. Silver is where the real engineering effort lives — and MERGE is the mechanism&lt;/H3&gt;&lt;P&gt;Bronze is fidelity. Gold is a contract. Silver is where you actually earn your keep:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Standardize types and naming&lt;/LI&gt;&lt;LI&gt;Deduplicate on natural/business keys&lt;/LI&gt;&lt;LI&gt;Enforce data quality rules (nulls, referential integrity, ranges)&lt;/LI&gt;&lt;LI&gt;Join and enrich against reference/dimension data&lt;/LI&gt;&lt;LI&gt;Apply domain-specific business rules&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;The mechanism that makes all of this idempotent is Delta's MERGE:&lt;/P&gt;&lt;PRE&gt;MERGE INTO silver.entity_table AS target
USING staged_updates AS source
ON target.business_key = source.business_key
   AND target.effective_date = source.effective_date
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *&lt;/PRE&gt;&lt;P&gt;One subtlety worth calling out: if your domain has legitimately repeating keys (e.g., effective-dated HR or reference data), your dedup/merge key &lt;STRONG&gt;must&lt;/STRONG&gt; include the version/effective-date column. Keying only on the natural identifier will silently collapse valid history into a single row — a bug that's easy to introduce and painful to find after the fact.&lt;/P&gt;&lt;H3&gt;Takeaways&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;Keep Bronze dumb and durable; put correctness in Silver where it can be revised&lt;/LI&gt;&lt;LI&gt;Don't assume Gold means "another copy" — default to views, materialize only with a measured reason&lt;/LI&gt;&lt;LI&gt;MERGE-based up-serts are what make reprocessing safe; get your key design right, especially for versioned/effective-dated data&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Curious how others have handled the Gold view-vs-table decision on their own Lakehouse migrations — would love to compare notes in the replies.&lt;/P&gt;</description>
      <pubDate>Thu, 16 Jul 2026 15:43:26 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163206#M1364</guid>
      <dc:creator>TriambakR</dc:creator>
      <dc:date>2026-07-16T15:43:26Z</dc:date>
    </item>
    <item>
      <title>Re: Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram</title>
      <link>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163209#M1367</link>
      <description>&lt;P&gt;I want to thank you for re-kindling my passion for data. This was a great overview of the medallion architecture!&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 16 Jul 2026 16:24:14 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163209#M1367</guid>
      <dc:creator>sasidharan_gs</dc:creator>
      <dc:date>2026-07-16T16:24:14Z</dc:date>
    </item>
    <item>
      <title>Re: Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram</title>
      <link>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163211#M1369</link>
      <description>&lt;P&gt;Insightful and well articulated&lt;/P&gt;</description>
      <pubDate>Thu, 16 Jul 2026 16:32:04 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163211#M1369</guid>
      <dc:creator>ashna_jindal</dc:creator>
      <dc:date>2026-07-16T16:32:04Z</dc:date>
    </item>
    <item>
      <title>Re: Medallion Architecture in Practice: The Design Decisions Nobody Puts in the Diagram</title>
      <link>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163218#M1370</link>
      <description>&lt;P&gt;Great work, man! Even though I don't know much about this field, your article made me curious and motivated me to read more about it. Thanks for sharing such valuable insights.keep posting&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 16 Jul 2026 17:11:01 GMT</pubDate>
      <guid>https://community.databricks.com/t5/community-articles/medallion-architecture-in-practice-the-design-decisions-nobody/m-p/163218#M1370</guid>
      <dc:creator>Sbm_dracarys</dc:creator>
      <dc:date>2026-07-16T17:11:01Z</dc:date>
    </item>
  </channel>
</rss>

