Batches, Serial Numbers, and Traceability
When something goes wrong — a contaminated ingredient, a faulty component, a counterfeit — you need to answer two questions within hours:
- Backward trace: where did this come from?
- Forward trace: where did it all go?
In regulated industries, being unable to answer is a criminal matter, not a service issue.
Batch vs serial
| Batch / Lot | Serial number | |
|---|---|---|
| Granularity | A group of units made or received together | One individual unit |
| Quantity | Many | Always 1 |
| Used in | Food, pharma, chemicals, textiles, electronics components | Machines, vehicles, appliances, IT equipment, medical devices |
| Purpose | Recall, expiry, quality characteristics | Warranty, service history, ownership, theft |
| Typical volume | Thousands of batches | Millions of serials |
Both can apply: a serialised medical device belongs to a manufacturing batch.
Batch management
The batch record
batch(
material_id, batch_number,
production_date, expiry_date, best_before_date,
next_inspection_date,
vendor_batch_number, -- their number, for backward trace
country_of_origin,
status, -- UNRESTRICTED | RESTRICTED | BLOCKED | QUARANTINE
characteristics JSONB, -- assay %, moisture, colour, tensile strength, grade
created_at,
PRIMARY KEY (material_id, batch_number)
)
Batch characteristics
Batches of the same material differ measurably, and customers care:
Fabric batch B2601: shade code 4A-127, GSM 182, shrinkage 3.1%
Fabric batch B2602: shade code 4A-129, GSM 178, shrinkage 3.4%
Batch determination selects which batch to issue based on rules: FEFO, matching shade, minimum assay, remaining shelf life ≥ customer requirement. In apparel, shipping two different dye lots in one order is a defect — the garments won’t match. This is real, expensive, and exactly what batch characteristics exist to prevent.
Shelf life
Total shelf life: 365 days
Minimum remaining at goods receipt: 270 days ← reject inbound stock that's too old
Minimum remaining at delivery: 120 days ← per customer; retailers set this contractually
FEFO picking is mandatory for perishables. Expired stock must be automatically blocked, and near-expiry stock reported so it can be sold down or donated before it becomes a write-off.
Batch status
- Unrestricted — usable
- Restricted — usable only for specific purposes
- Quarantine / QI — awaiting test results
- Blocked — failed quality, under investigation, or recalled
A status change must propagate: blocking a batch has to block every unit of it, wherever it is, including stock already allocated to orders.
Batch derivation
In production, the output batch inherits characteristics from the input batches:
Input: Resin batch R-100 (purity 99.2%), Additive batch A-55 (purity 98.0%)
Output: Compound batch C-780 (derived purity 99.0%)
Rules: minimum, maximum, weighted average, or copy. This is standard in process manufacturing.
Serial number management
Serial profiles
Configuration decides when a serial number is required:
| Event | Serial required? |
|---|---|
| Goods receipt | Capture the vendor’s serial |
| Production confirmation | Assign your own |
| Goods issue / delivery | Record which specific unit shipped |
| Stock transfer | Track movement |
| Customer installation | Link to an installed-base record |
| Service / repair | Attach service history |
The equipment / installed base record
A serial number that lives at a customer site becomes an equipment record:
equipment(id, serial_number, material_id, batch,
customer_id, installation_address, installed_at,
warranty_start, warranty_end, service_contract_id,
parent_equipment_id, -- component installed in a machine
status, current_location)
This is the foundation of aftermarket service: warranty validation, service history, spare-part compatibility, and recall targeting. See Manufacturing → quality.
The traceability chain
Vendor batch V-8821
│ goods receipt
▼
Your batch R-100 ──┐
│ production order 4711
Your batch A-55 ──┤
▼
Output batch C-780
│ production order 4890
▼
Finished batch F-9001, serials SN00001–SN05000
│ deliveries
├──▶ Customer A: SN00001–SN01200
├──▶ Customer B: SN01201–SN03000
└──▶ Distributor C: SN03001–SN05000 (onward, unknown)
The chain breaks at the distributor. This is why regulated supply chains push “one step forward, one step back” obligations onto every participant — nobody sees the whole chain, but everyone can reconstruct it link by link.
The data that makes it work
Every consuming and producing document must record the batch/serial:
material_document_item(
..., batch, serial_numbers TEXT[],
reference_document, reference_item
)
production_order_component(order_id, material_id, batch_consumed, quantity)
production_order_output(order_id, material_id, batch_produced, serials TEXT[])
delivery_item(delivery_id, material_id, batch, serials TEXT[], customer_id)
The trace query is a recursive graph walk over these links. Design it as one from the start; bolting it on later means backfilling data that was never captured.
WITH RECURSIVE trace AS (
SELECT order_id, material_id, batch_produced AS batch, 0 AS depth
FROM production_order_output WHERE batch_produced = :suspect_batch
UNION ALL
SELECT po.order_id, poc.material_id, poc.batch_consumed, t.depth + 1
FROM trace t
JOIN production_order_output po ON po.batch_produced = t.batch
JOIN production_order_component poc ON poc.order_id = po.order_id
WHERE t.depth < 20
)
SELECT * FROM trace;
Regulatory requirements
| Regulation | Scope | Requirement |
|---|---|---|
| EU 178/2002 | Food | One step forward, one step back; trace within 4 hours |
| FSMA 204 (US) | High-risk foods | Key Data Elements at Critical Tracking Events |
| EU FMD | Pharma | Unique identifier per pack, verified at dispense |
| US DSCSA | Pharma | Full unit-level electronic traceability |
| EU MDR / US UDI | Medical devices | Unique Device Identification |
| REACH / GHS | Chemicals | Substance registration, safety data sheets |
| 21 CFR Part 11 | FDA-regulated | Electronic records and signatures: audit trail, non-repudiation, validated system |
| GS1 EPCIS | Cross-industry | The standard event format for what/when/where/why |
21 CFR Part 11 — what it means for a developer
If you build software touching FDA-regulated records:
- Every record change is audit-trailed with user, timestamp, old value, new value, and reason
- Electronic signatures are bound to records and cannot be transferred
- The system must be validated (IQ/OQ/PQ) with documented evidence
- Audit trails cannot be modified or deleted, by anyone, including admins
- Access is role-controlled and reviewed
This is a heavy compliance burden that changes how you design, test, and deploy. Budget for it explicitly.
Recall
The test of the whole system:
1. Trigger — customer complaint, internal test failure, supplier notification
2. Scope — trace forward from the suspect batch to every customer and location
3. Quantify — how much shipped, how much on hand, how much consumed
4. Block — set batch status to Blocked everywhere; halt shipments
5. Notify — customers, distributors, regulators (within mandated hours)
6. Recover — returns, disposal, credit notes
7. Report — regulator submission, root cause, CAPA
8. Post-mortem — mock recalls at least annually to prove it works
Mock recalls are a required practice in food and pharma. The regulator asks you to trace a batch and gives you a deadline (often 2–4 hours). If your system can’t do it, you fail an audit. Building the trace report before you need it is not optional.
GS1 standards
| Identifier | What |
|---|---|
| GTIN | Global Trade Item Number — the product |
| SSCC | Serial Shipping Container Code — a logistics unit |
| GLN | Global Location Number — a party or place |
| GRAI / GIAI | Returnable asset / individual asset |
| GS1-128 / DataMatrix | Barcode carriers with application identifiers |
| EPCIS | Event data standard — the “what, when, where, why” of a movement |
Application Identifiers encode structured data in a barcode:
(01)09501101530003(10)B2601(17)261231(21)SN00001
↑ GTIN ↑ batch ↑ expiry ↑ serial
If you’re parsing barcodes in a warehouse app, learn AI parsing — it saves inventing a proprietary format that breaks on the first customer who uses GS1 properly.
Design rules
- Decide batch/serial requirements per material at design time. Retrofitting means the historical data simply doesn’t exist.
- Batch is part of the stock key — see Inventory Model.
- Every movement, consumption, and output records the batch/serial. No exceptions, including scrap and samples.
- Model the trace as a graph and build the recursive query early.
- Batch status changes propagate immediately to all stock and all open allocations.
- Never reuse a batch or serial number, even after the stock is gone.
- Serial arrays get big. For high-volume serialisation, a separate
serial_movementtable beats an array column. - Run a mock recall drill on your own build before go-live. The gaps will surprise you.