DEV Community

Isaac Mwendwa Muthui
Isaac Mwendwa Muthui

Posted on Originally published at factoraerp.com

Model Line Changeover as a State Machine So the Next SKU Cannot Start Before Clearance

By Isaac Muthui, CEO, Tamalaki Business Network Ltd. Originally published at factoraerp.com.

If you build production or MES/ERP software for food manufacturers, here is a failure mode worth designing out: the next product's production order can start on a line while the previous product is still, in practice, on it.

In small and mid-sized food and agro factories in Kenya, where I work, changeovers between SKUs on the same line (flavoured yoghurt to plain, peanut snack to plain snack, spice blend A to blend B) are where residue, leftover labels, work in progress and stale machine settings carry over. The operational fix is a line clearance checklist. The software fix is to make clearance an explicit event in the model, so the system cannot start the next order until it has happened.

This post covers how to model that, plus the eight-point checklist that acts as the spec.

The anti-pattern: production orders without a line state

A common design looks like this:

  • production_order has status (planned, in_progress, completed) and a line_id.
  • Starting an order just flips its status to in_progress.
  • Nothing stops two orders being in_progress on the same line, or a new order starting while the previous one has unreturned WIP and packaging.
  • Cleaning, if recorded at all, lives in a separate log with no link to either order.

The result: the batch record says product B started at 12:00, but nothing in the data says whether product A was ever cleared off the line.

Model the line, not just the order

Give each line its own state machine, and make orders depend on it:

RUNNING(order A)
   │  close_order(A): final qty, lot, WIP/packaging returned
   ▼
CLOSED_OUT(A)
   │  record_cleaning(programme, by, finished_at)
   ▼
CLEANED
   │  verify_clearance(checker ≠ cleaner, checks[], result)
   ▼
CLEARED ──(fail)──► CLEANED   (re-clean, re-verify)
   │  setup(order B): recipe/BOM version, settings, packaging, coder
   ▼
SETUP(B)
   │  first_off_qc(B, result)
   ▼
RUNNING(order B) ──(fail)──► SETUP(B)
Enter fullscreen mode Exit fullscreen mode

Rules worth enforcing in code, not in the UI:

  1. One active order per line. start_order(B) is only valid when the line is in SETUP(B) and first-off QC has passed.
  2. No skipping states. There is no transition from RUNNING(A) to RUNNING(B). Not even for admins without a recorded override.
  3. Changeover type drives the required checks. Derive the type from the from/to products: same product, different pack (light); different recipe (full); allergen profile changes from contains to free-from (allergen). Each type maps to a cleaning programme and a set of required verification checks.
  4. Segregation of duties. verify_clearance.checked_by must differ from record_cleaning.cleaned_by, and the releaser must hold a QA/supervisor role.
  5. Close-out is a precondition. close_order(A) should fail if issued packaging or WIP has not been returned, consumed or explicitly scrapped.

A minimal schema sketch:

create table line_changeover (
  id               uuid primary key,
  line_id          uuid not null references line(id),
  from_order_id    uuid not null references production_order(id),
  to_order_id      uuid references production_order(id),
  changeover_type  text not null check (changeover_type in ('light','full','allergen')),
  state            text not null check (state in
                     ('closed_out','cleaned','cleared','setup','released')),
  cleaning_programme text,
  cleaned_by       uuid references app_user(id),
  cleaned_at       timestamptz,
  checked_by       uuid references app_user(id),
  checked_at       timestamptz,
  released_by      uuid references app_user(id),
  released_at      timestamptz,
  constraint checker_not_cleaner check (checked_by is null or checked_by <> cleaned_by)
);

create table changeover_check (
  changeover_id uuid references line_changeover(id),
  check_code    text not null,  -- e.g. 'wip_removed','no_residue','old_labels_removed'
  result        text not null check (result in ('pass','fail','n_a')),
  note          text,
  recorded_by   uuid references app_user(id),
  recorded_at   timestamptz not null default now()
);
Enter fullscreen mode Exit fullscreen mode

And the guard on starting an order:

function startOrder(line: Line, order: ProductionOrder, user: User) {
  const co = line.currentChangeover;
  if (!co || co.toOrderId !== order.id) throw new Error("No changeover for this order");
  if (co.state !== "setup") throw new Error(`Line not ready: ${co.state}`);
  if (!requiredChecksPassed(co)) throw new Error("Clearance checks incomplete");
  if (!order.firstOffQc?.passed) throw new Error("First-off QC not passed");
  if (!user.roles.includes("line_release")) throw new Error("Not authorised to release line");
  co.state = "released";
  co.releasedBy = user.id;
  co.releasedAt = now();
  order.status = "in_progress";
}
Enter fullscreen mode Exit fullscreen mode

The point is not the exact code. It is that "the line is cleared" becomes a row with names and timestamps, and starting the next order depends on it.

The eight checks (your spec)

These become the check_code values in changeover_check. Your customer's SOP and HACCP plan decide which apply to each changeover type.

  1. Previous product and batch closed out. Final quantity and lot recorded; WIP, part-filled containers and samples removed or segregated; unused materials and packaging returned under lot identity.
  2. Food-contact equipment cleaned or sanitised per SOP (or the CIP programme run) for this changeover type. Tetra Pak Kenya describes CIP as preparing equipment after a run or when switching a line from one recipe to another.
  3. Visual check, plus any required verification, confirms no previous residue, done by someone other than the cleaner.
  4. Only the new product's packaging, labels and coding on the line. Old labels and lids removed; coder changed and a printed sample checked.
  5. Allergen switch handled. Stricter clean, dedicated tools, colour-coding, allergen ingredients removed from the area.
  6. Correct recipe/BOM version and process settings loaded, and the staged material lots match those issued to the new order.
  7. Line documents updated. From-product/batch, to-product/batch, times, who cleared and who released.
  8. First-off / start-up QC passed before full-speed running; start-up packs held until they pass.

Why this matters for compliance-shaped data

Kenyan food factories work against guidance like the Ministry of Health Checklist for Food Hygiene Licensing (April 2023), which expects cleanable food-contact surfaces, hazard monitoring during processing, cleaning and disinfection SOPs and a HACCP plan, and the East African code of practice EAS 39:2001, which calls for documented cleaning programmes with records showing they were followed. KEBS factory inspections for the Standardization Mark look at process controls and records. Software doesn't make a plant compliant. But if your data model stores clearance as a first-class event, the records an inspector or customer asks for already exist, linked to the batches they cover.

It also pays off for traceability: when a complaint arrives, you can answer which run preceded the affected batch, what changeover type it was, and who released the line.

Practical tips for builders

  • Default to blocked. A new line changeover starts in closed_out, never released.
  • Make overrides loud. If an override exists, require a reason and a second approver, and surface it on the batch record.
  • Expose changeover time. Store state timestamps so planners can see real clearance durations and put them in the schedule.
  • Offline matters. Many plant floors have patchy connectivity. Let checks be recorded on a tablet offline and synced, but don't allow released until the sync confirms the required checks.

Where we apply this

At FactoraERP we link production orders to recipes, BOM versions, issued lots and batch records for food and agro manufacturers in East Africa. Modelling the changeover explicitly is what lets the batch record show which lots went into which run and who released the line.

The operations version of this checklist, with an FAQ for factory teams, is on our blog: Line Clearance Checklist: 8 Checks Before You Start the Next Product on a Kenyan Food Line.

Operations guidance, not legal advice.

Top comments (0)