Note 27 · Microsoft Fabric

Bronze Typing: Is Ingesting Everything as Strings a Good Idea?

Argue for typing published columns in bronze (or the earliest stable layer) and banning ritual CAST in silver and gold.

19 August 2026 9 min read

Key takeaways

  • Publish definitive types at bronze (or the earliest stable clean view).
  • Ban ritual CAST on unchanged physical columns in silver and gold.
  • Allow UNION alignment casts only when localized next to the UNION.
  • Gold owns typed unknown-row literals that match relationship types.
  • Lint CAST noise in CI; allowlist only with a written reason.
  • Rematerialize dependents when the type contract changes.

Re-CASTing the same physical column in every layer feels careful. It is usually how drift multiplies. Bronze casts to decimal. Silver casts again "to be safe." Gold casts a third time and invents an unknown literal with yet another type. Consumers inherit a guessing game.

Type each published column once, as early as you dare (usually bronze, sometimes the first stable clean view). Silver and gold keep aliases, business calculations, and typed unknown-row literals only. UNION alignment casts are the exception, not the lifestyle. Lint the rest.

Named model: type once early

  • Bronze publish: definitive types at the earliest stable publish boundary once the source contract is understood.
  • Silver calculate: grain, aliases, and business rules on inherited types. No ritual re-CAST of the same physical field.
  • Gold shape: facts, dims, and typed unknown members that match relationship types.
  • Exceptions: UNION alignment casts stay named and local; derived columns may CAST; rematerialize when the contract moves.
  • Contract: downstream layers consume types. They do not renegotiate them.

Named model: bronze publishes types once; silver calculates; gold shapes facts and typed unknowns

Figure 1. Type each column once, as early as you dare. Downstream layers inherit the contract. They do not reinvent CAST for the same physical column.

Context and constraint

A common pattern is silver SQL that spends more lines re-declaring types than expressing business rules. The looked disciplined. The types still disagreed with the because gold had its own CAST folklore. Rematerializing half the lineage after a type change made the cost obvious.

Ritual CAST in silver and gold creates parallel truths: float here, decimal there, stringly dates in a third notebook. Unknown members need explicit typed literals in gold, not accidental nulls that break relationships. When the contract changes, rematerialize dependent lineage on purpose. Half-refresh is how yesterday's types haunt tomorrow's measures.

Figure 2 is the Learn surface where mapping and typing show up in a pipeline. The product lets you cast. The platform still needs a rule about where the contract lives.

Configure mapping in a copy data pipeline

Figure 2. Mapping and type choices appear early in the ingest path. Put the durable contract at the earliest stable publish boundary, not in every downstream SELECT. Source: Microsoft Learn: copy data activity.

Design

1. Choose the earliest stable typing boundary

Prefer bronze (or the thin clean view on trusted shortcuts) once the source contract is understood. Typing in raw landing before the source stabilizes just freezes churn. Typing only in gold pushes ambiguity through every upstream consumer. Pick the layer where the column is published for reuse, and declare types there. Figure 1 is that boundary drawn as three jobs.

2. Ban ritual CAST in silver and gold

Silver transforms grain and business rules. Gold shapes facts and dims for consumption. Neither should repeat CAST(x AS DECIMAL(18,2)) because someone was nervous. Nervousness belongs in tests against the bronze contract. If silver must CAST, it should be because it creates a new derived column, not because it distrusts bronze. Figure 3 is the comfort-blanket failure next to the preferred path.

Anti-pattern of CAST in every layer versus typing once in bronze with silver and gold inheriting

Figure 3. Ritual CAST multiplies drift. Type once in bronze. Calculate downstream. Keep UNION alignment casts next to the UNION and lint the rest.

3. Allow UNION alignment casts as named exceptions

UNION and UNION ALL branches need aligned types. Those casts are real engineering. Name them in comments or helpers, keep them next to the UNION, and do not copy them into every select list "for consistency." Consistency without a UNION is noise.

4. Gold owns typed unknown rows, not type renegotiation

Unknown and not-applicable members need keys and literals that match relationship types. That is gold work. Inventing a string 'unknown' next to an int64 key is how blank visuals appear later. Keep unknown-row typing in the same contract as the fact grain. Figure 4 is the relationship-safe unknown versus the quiet break.

String UNK next to a BIGINT key breaks relationships; a typed dim unknown key keeps the model honest

Figure 4. Unknown members are where typing discipline shows. Match key types. Document the convention beside the grain. Rematerialize when the contract moves.

5. Lint CAST noise

SQLFluff or equivalent rules should fail noisy CAST patterns in silver and gold except allowlisted files (UNION helpers). Linting beats code review folklore. If the team can explain why a CAST is required, put it on the allowlist with a reason. If they cannot, delete it.

6. Rematerialize after type contract changes

Changing bronze types without rebuilding dependents leaves mixed generations in the lake. Plan rematerialization as part of the type change, not as a surprise incident. Document which MLVs and tables must rebuild and in which order. Figure 4 carries that clause on purpose: half-refresh is a type bug with a lag.

How to introduce the ban without a holy war

Start with a report of CAST density per layer. Pick the top noisy gold objects and delete redundant casts while proving parity. Add lint in warn mode, then error mode for new changes. Do not rewrite every model in one PR. The goal is a ratchet: new ritual CAST stops landing, old ritual CAST dies during normal touches. Pair the ratchet with a short ADR so reviewers have something to cite besides taste.

Unknown members are where typing discipline shows

Teams that ban ritual CAST still trip on unknown rows: a fact left outer joins a dim, someone coalesces a missing key to the string "UNK", and the relationship dies. Decide unknown key types with the same seriousness as numeric types. Put the unknown member in the dimension with a typed key. Reference that key from facts. Document the rule beside the grain statement so a future notebook does not invent a second unknown convention for the same entity.

Failure modes

CAST as comfort blanket. Every layer "fixes" types; none owns them. Figure 3 is that failure drawn.

Stringly typed keys in one layer. Relationships and joins become seasonal.

Unknown literals with accidental types. Semantic models fail quietly. Figure 4 is the break and the fix.

Half-refresh after type changes. Old parquet files keep old types in practice.

Lint optional. Reviewers tire; CAST ritual returns.

Typing in unstable raw. You cement source dump chaos as platform truth.

What to copy / what not to copy

Copy

  • Published columns receive definitive types at bronze (or documented earliest stable layer).
  • Silver/gold ritual CAST on unchanged physical columns is banned.
  • UNION alignment casts are allowed and localized.
  • Gold unknown-row literals must match relationship types.
  • CI lint fails CAST noise outside allowlists.
  • Type contract changes include an explicit rematerialization plan.

Do not copy blindly

Early typing couples you to source understanding sooner. Late typing couples every consumer to ambiguity longer. Lint false positives need an allowlist process or people bypass CI. Rematerialization costs capacity; skipping it costs incidents. Derived columns will still CAST. The rule is about ritual retyping of the same physical field, not about forbidding SQL.

Primary references: Spark SQL data type docs and Fabric lakehouse medallion guidance on Microsoft Learn. Pair them with a lint rule set in the repo so the contract is enforceable.

Closing

If every layer retypes the same column, you do not have a type system. You have a habit.

Type once early. Calculate downstream. Lint the ritual away. Rematerialize when the contract moves. The platform gets quieter, and so do the blank visuals.