# Lot data lives at birth.

*31 July 2026 · the launch journal*

Ask a typical traceability integration where the lot's expiry date lives and you get an architecture diagram: the events reference a lot number, the lot number keys into the batch table, the batch table lives in the ERP, and the ERP answers queries for anyone with a service account. Which is to say: the expiry date lives *at home*, and the events that travel out into the world carry a foreign key into a database the rest of the world cannot see.

That design fails on the exact day traceability exists for. A trace-back crosses a company boundary — your co-packer's events, your distributor's events, yours — and every party's lot attributes are locked in a side-table the *other* parties don't share. The chain of events reconstructs beautifully; the question "which of these lots expires next month" dies at the first boundary, and the answer gets rebuilt over email, which is how a trace that should take minutes [takes days](https://visibility.cloud/).

EPCIS 2.0 has a specific mechanism for exactly this, and it is underused because its name sounds like bureaucracy: **ILMD — instance/lot master data**. The contract is simple and strict: attributes of a *specific* lot or instance (as opposed to attributes of the product class) are stamped **once, on the event that creates the objects** — the commissioning event — and are immutable after. The data travels *inside the record*, so any holder of the events holds the answers.

## The fixture

A lot of 480 units is born on a filling line; the commissioning event carries its identity and its birth certificate in one artifact — validated against the pinned official EPCIS 2.0.1 schema, exit `0`:

```json
{ "type": "ObjectEvent",
  "eventTime": "2026-07-31T05:12:00.000Z", "eventTimeZoneOffset": "-06:00",
  "quantityList": [
    { "epcClass": "urn:epc:class:lgtin:0614141.011111.LOT2607A",
      "quantity": 480, "uom": "EA" } ],
  "action": "ADD",
  "bizStep": "commissioning", "disposition": "active",
  "readPoint": { "id": "urn:epc:id:sgln:0614141.00888.line2" },
  "bizLocation": { "id": "urn:epc:id:sgln:0614141.00888.0" },
  "ilmd": {
    "cbvmda:lotNumber": "LOT2607A",
    "cbvmda:productionDate": "2026-07-31",
    "cbvmda:itemExpirationDate": "2026-11-28" } }
```

Three things to read closely:

- **The identity is lot-grain.** `urn:epc:class:lgtin:…LOT2607A` — an LGTIN, GTIN plus lot — in a `quantityList`, because these 480 units are interchangeable within the lot and nobody serialized them. Lot grain is the honest grain for most food and many pharma flows; [serial grain](/journal/four-event-types-one-decision-tree/) is a per-unit decision, not a default.
- **The attribute names are vocabulary, not invention.** `cbvmda:` is the CBV master-data namespace (`urn:epcglobal:cbv:mda:`, mapped in the pinned JSON-LD context), and CBV 2.0 §9.2 defines the trade-item attribute set — `lotNumber`, `productionDate`, `itemExpirationDate` and their siblings, GDSN-aligned. Inventing `"expiry_dt"` here would be the [same dialect mistake](/journal/say-shipping-not-shipped/) as inventing a bizStep: readable by you, opaque to every verifier you'll never meet.
- **`action: ADD` at `commissioning` is what licenses ILMD.** Writable at object creation, never after — a downstream shipping event that tried to "update" the expiry is mis-modeled by definition. Downstream events *reference* the lot; they do not re-describe it.

## One lot, one story

Downstream, the contract inverts: every later event carries the **same LGTIN** in its quantity list — the ship event, the receive event, the [aggregation onto the pallet](/journal/model-the-pallet-before-it-exists/) via `childQuantityList` — and none of them repeats the attributes. The join is by identity, and the attributes are wherever the commissioning event is, which is *in the same record*. A receiver who has never met your ERP runs one query — events for `lgtin:…LOT2607A` — and holds the full story: born 07-31 on line 2 at Plant 2, expires 11-28, packed, shipped, received. Self-contained is the whole point: the trace answer has no external dependencies, no service account on someone else's ERP, no side-table that didn't travel.

This is also, not incidentally, the shape food-safety regulation keeps converging on. A traceability lot code with its source and dates, carried with the records that reference it — a conformant commissioning event with ILMD already contains the key data elements a sortable-spreadsheet request asks for, at exactly one place in the record. The barcode on the case ties in the same way: AI (10) on the label parses to the same lot the events carry — the label-to-record contract [barcoding.dev](https://barcoding.dev/) handles on the barcode side.

Two boundaries keep the mechanism honest. ILMD is for *instance/lot* attributes — this lot's dates — never for class attributes like product description, which belong in master data proper ([the document header carries those](/journal/ship-the-dictionary-with-the-data/), next in this series). And ILMD is immutable because the lot's birth facts don't change; a wrong entry is corrected the append-only way, by `errorDeclaration` and a corrective event, never by edit.

The fixture above is yours to check: `npx epcis.dev validate` against the pinned schema, exit `0`, [twelve microseconds](/journal/no-eval-at-validation-time/). Stamp the lot at birth, reference it forever, and the next trace-back that crosses your co-packer's boundary carries its own answers.

*Sources: EPCIS 2.0.1 ILMD model (pinned `epcis-json-schema.json`, `ilmd` definition; digests at [/conformance/](/conformance/)); CBV 2.0 §9.2 trade-item master-data attributes; `cbvmda` namespace mapping in the pinned `epcis-context.jsonld`; fixture validated with the packaged CLI 2026-07-31, exit 0.*

---

**Proof, not adjectives.** This build could not verify the gateway's test suite green, so no sentence on this page claims a passing run — the last verified run is recorded in the repository's own CI, not here. Live on this origin, no key: POST /translate, /validate, /hash. No conformance attestation has ever been issued. The dated ledger is /what-ships-today/.
