Skip to content
About
Main content

Variant and union columns

When is a variant column the right escape hatch, and what keeps it from eating the schema?

Variant, union, and the licensed escape hatch

Some payloads really are open: per-tenant custom fields, webhooks from third parties, device telemetry that changes with the firmware. Forcing them into a closed schema turns every customer onboarding into a deploy. That is an organizational cost so high that people route around it with a stringified JSON blob in a text . The blob is the same thing as a column, with worse tooling.

The mechanism

A variant column is a column whose type is "any self-describing value": the value carries its own structure, like a JSON document. Usually the system also shreds frequently present paths into real sub-columns. means that if 90% of records have custom.bin_number, the engine stores that path as its own typed column behind the scenes. This partly recovers scan speed.

A is the closed cousin: a field that may be one of an enumerated set of alternatives (for example, integer or string). Because the set is finite, the system can check it. A variant is open, so it cannot be checked.

What a variant buys, and what kills it

What a variant buys is . The escape hatch is bounded to one column instead of contaminating the whole record.

What kills it is scope creep. Writing into the variant is always the locally cheapest action. Without a rule against it, everything ends up there, and you have with extra steps.

The rule against it is a : a path that is present in more than X% of records for more than Y days is promoted to a declared column. Without a promotion policy, the escape hatch becomes the design.

A variant is a licensed, scoped region of late binding; it needs a promotion path or it eats the schema.