1 April 2026 · Wei Liang Tan

Properties that drown the dictionary

Search strings, full SKUs, and concatenated timestamps look harmless in a test payload. In production they make every report a unique snowflake.

Close view of a person writing on lined paper with a black pen

Cardinality is a dull word for a sharp problem. Each distinct value of a property is a bucket. If the property is search_query, you do not have buckets. You have a pile of one-off strings that no weekly review can read.

We still see plans that attach raw SKU, full URL, and device_id to every event “just in case.” The just-in-case fields make it impossible to answer a simple question: how many people selected pickup versus delivery on Thursday.

The dictionary should list allowed values where the set is small. fulfilment: pickup | delivery | locker. For large sets, store an identifier that already exists in the product database, and join later in the warehouse if you must. Do not ask the event stream to be the catalogue.

Timestamps inside property values are a special nuisance. event_time already exists. A property named created_at_local with a formatted string such as 18/04/2026 14:03 +08 is not a dimension. It is graffiti.

During schema planning we mark every proposed property as low, watched, or forbidden. Forbidden is not a moral judgement. It is a promise that the payload will stay small enough for a human to read in a QA session.

Back to the journal