Restaurants & Food Service// definition

External IDs: the mapping table nobody designs until it breaks

In short

The map between your menu ids and the POS's identifiers is the contract that lets 2 catalogues talk, and it is a versioned artefact with an owner rather than a dictionary somebody seeded once. Four ordinary events invalidate it without producing a single error — an item deleted and recreated, a modifier moved between groups, a location cloned from another, and a platform migration.

Key takeaways

  • The map covers 3 levels — item, modifier and location — and a break at the modifier level is the hardest to see.
  • Four routine events invalidate mappings without an error: recreate, regroup, clone and migrate.
  • Never delete a mapping row. Retire it with a timestamp, or you lose the ability to explain last quarter's orders.
  • A drift report with no named owner and no deadline is not a control — it is a weekly email that changes nothing.

Every order you write into a till depends on 1 quiet artefact: the table saying that your item 4417 is the POS's item with its own identifier, that your "oat milk" option is that platform's modifier, and that both of those statements are true for this location. Teams build it in an afternoon as a lookup dictionary and then discover, usually during a service, that it is the most load-bearing object in the integration.

The difference between a dictionary and an artefact is ownership and history. An artefact has a person responsible for it, a record of when each row was last verified, and a rule for what happens when a row stops being true. A dictionary just has entries, and no way to tell a stale one from a correct one.

Three levels the map has to cover, not one

  • Item level. Your sellable product to the POS's menu item. This is the level everyone builds, and it is the level that produces a loud failure when it breaks — the order is rejected.
  • Modifier level. Your option to the POS's modifier, inside the modifier group the platform expects it in. This level fails quietly: the order is accepted and the kitchen gets the wrong instruction.
  • Location level. The same conceptual item can carry a different identifier per store, so every row is scoped to a location or explicitly marked as global. Assuming global is how an integration that works at one store fails at the other four begins.
  • Beyond those 3 sit the channel ids — the aggregator's own identifier for the same dish — which is a second map with the same design and a different owner.

The modifier level deserves the most care because its failure mode is silent and edible. An allergy-relevant option mapped to the wrong modifier does not raise an error anywhere; it produces a plate. The lines and modifiers underneath a check are described in the check: what an online order turns into, and the map is what fills them.

Four ordinary events that break it without an error

EventWhat actually happensThe signal that catches it
An item is deleted and recreated in the POSA manager fixes a typo by rebuilding the item; the name and price look identical and the identifier is newA mapped identifier that no longer appears in the catalogue pull, plus an unmapped item with a matching name and price
A modifier moves to a different groupThe modifier still exists, so the id resolves, but it is no longer valid on the item you are sending it withA diff of group membership between pulls, not a diff of ids
A location is cloned from anotherNew store, catalogue copied, every identifier fresh; your rows still point at the source store's idsAny location whose mapped-id set is identical to another location's — a clone is 100% overlap where 2 real stores are never that close
A platform migration or a merchant re-onboardingThe entire id namespace changes at once, including ids that were stable for yearsA pull in which the unmatched share crosses a threshold — say 30% — which should halt the sync rather than repair it row by row
How each event breaks the map, and the signal that detects it

The third row is the one that produces the strangest support tickets, because orders succeed. They are written against real identifiers belonging to a different restaurant's catalogue, so the wrong thing is made in the right building. The fourth row is the one to design a stop for: a migration is not a set of individual drift events and should never be repaired as though it were.

What a row has to carry to be repairable

  1. Both identifiers, plus the location scope the pairing is valid for.
  2. The provenance of the mapping: automatically matched, confirmed by a person, or imported during onboarding. These 3 do not deserve equal trust.
  3. The evidence used at match time — name and price as they were then — so a later mismatch can be explained rather than guessed at.
  4. A last-verified timestamp, updated by the reconciliation job, so age becomes visible.
  5. A retired-at field instead of a delete, because an order placed in March has to remain explainable in September.

The reconciliation job, and the person it reports to

  1. Pull the full catalogue per location on a schedule that fits the platform's limits, rather than the one you would prefer.
  2. Diff by identifier first: mapped ids missing from the pull, and catalogue ids with no mapping.
  3. For anything unmatched, fingerprint by name plus price plus group membership, and propose — never auto-apply — a re-match for a human to confirm.
  4. Classify the result into order-blocking (an item you sell has no valid mapping) and non-blocking (an unmapped item nobody orders through your channel).
  5. Fail loudly on order-blocking classes before service, and hold everything else for a named owner with a deadline.
  6. Record every accepted repair with who confirmed it, so the map has a history rather than a current state.

Step 5 is where most of these jobs die. A drift report that lands in a shared inbox with no owner and no deadline is exactly the failure described in the reminder that changed nothing: an alert nobody is accountable for is not a control. The same reasoning applies to the event stream — a missed catalogue event has to be recoverable by the sweep, which is why the POS fired the event and nothing moved argues for reconciliation over more reliable listeners.

Identity mapping between 2 systems that both think they own the master record is not unique to restaurants; it is the same shape as the master-data problem in AI in logistics operations, and it responds to the same treatment. Where automated matching helps is in proposing candidates for a person to confirm, which is exactly the boundary we hold in AI agents and automation work: the model suggests, a named human accepts, and the acceptance is recorded.

One more consequence worth stating plainly: routing configuration is not part of this map. If an order is accepted with correct identifiers and still nothing appears at the pass, the map did its job and the store's configuration did not — the case handled in the order is in the POS and nothing prints.

A mapping table is not a lookup. It is a claim about 2 systems that was true on the day somebody made it, and nothing in either system is obliged to keep it true.

Give it an owner, a verification date and a retirement rule, and the integration stops surprising people. The rest of this silo sits under integrating with the POS on the counter, inside our restaurants and food service practice.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

Why does a menu item id mapping break when nothing changed on our side?

Because the change happened on the other side, and most of those changes produce no error. A manager deleting and recreating an item gives it a new identifier while the name and price stay identical; a modifier moved between groups keeps its id but stops being valid where you send it. Neither event notifies you, which is why a scheduled diff of the catalogue is the only reliable detection.

Should the mapping live in our system or in the POS?

In your system, as data you own and can version. Some platforms let you write an external reference onto their objects, which is useful as a secondary check, but it is not a substitute: you cannot rely on another system to preserve your identifiers through its own migrations, and you cannot query its history when a reconciliation question arrives.

What should happen when the reconciliation job finds a mapping that no longer resolves?

Stop the affected item from being ordered and raise it to a named owner, rather than guessing a replacement. An automatic re-match on name and price is fine as a proposal and dangerous as an action, because the 2 most common causes — a recreated item and a cloned location — both produce plausible-looking name matches that point at the wrong thing.

How often should the catalogue be reconciled against the POS?

Often enough that drift is caught before a service, and within whatever the platform's limits allow. A nightly full diff per location is a reasonable default for a small estate; larger estates usually need a change-detected sync during the day plus a full reconciliation overnight. The schedule matters less than having an owner who acts on the output.

  • pos
  • identifiers
  • catalog sync
  • restaurants
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation