Record Numbering
Human-readable references built from a token format, with counters held per entity and per period so sequences reset without anybody resetting them.
Record Numbering Overview
Record numbering gives records a human reference — INV-GB-2026-00042 — instead of making somebody quote a database ID.
Where to find it
Architect Panel → Data:
- Record Numbering — the console — schemes, formats and their counters
Why not just use the ID
Every record already has an ID, but an ID is a poor public reference. It is awkward to read out on the telephone, it carries no indication of what kind of record it is, and it discloses your volumes — anybody quoted ID 41 knows you have had about forty of these.
A reference is also stable in a way an ID is not. It survives a migration between systems, because it is data rather than a row position.
The format is a token template
A scheme holds a format assembled from tokens rather than a fixed prefix-and-number shape. A typical one reads:
{PREFIX}-{ENTITY}-{PERIOD}-{SEQ}
- PREFIX — a short code you set, such as
INVorINC. - ENTITY — the legal entity, so two companies never share a series.
- PERIOD — the current period, usually the year.
- SEQ — the counter, zero-padded to the width you set.
Because it is a template, you can drop tokens you do not need. A single-entity business with no period reset can run {PREFIX}-{SEQ} and get INC-000042.
Two records can never get the same number
Allocation is atomic, so simultaneous creation cannot produce a collision. This matters more than it sounds — a duplicated invoice number is a genuine accounting problem, not a cosmetic one, and it is exactly the failure a naive "take the highest and add one" implementation produces under load.
Gaps are normal
The counter only moves forwards. Deleting a record does not return its number to the pool, and an abandoned draft leaves a gap.
This is deliberate. Reissuing a number would mean two different records had held the same reference at different times, which is precisely what a reference exists to prevent. Do not treat the numbers as a count: a highest number of INV-2026-00500 does not mean five hundred invoices.
Pad generously
Padding is what keeps references sorting and aligning correctly. Choose a width you will not exhaust — five digits costs nothing and covers 99,999 records per period, where three digits looks tidy until the day it does not.
Worked example
A service desk uses INC- for incidents and REQ- for requests, so the prefix alone tells an agent what they are looking at before they open anything. A finance team uses {PREFIX}-{ENTITY}-{PERIOD}-{SEQ} for sales invoices, giving INV-GB-2026-00042 — readable, per-company, and per-year, from one scheme.
Recommendations
- Use distinct prefixes so the reference identifies the record type.
- Pad to five digits unless you have a reason not to.
- Include the entity token if you have more than one company, even if you only have two.
- Never explain a gap as an error — it is how the counter is meant to behave.
Setting Up a Numbering Scheme
A scheme binds a format to a specific field on a specific datastore, and owns the counter that fills it.
Where to find it
Architect Panel → Data:
- Record Numbering — the console — create schemes and inspect counters
- Datastores — the datastore and field the scheme writes to
What a scheme holds
- Datastore and field — where the number is written.
- Scheme key — a short identifier, so several schemes can target the same field for different record types.
- Entity — which legal company this counter belongs to.
- Prefix, format and padding.
- Period key and period value — how and when the sequence rolls over.
- Next value — the counter itself.
The counter is a row, not a field
This is the design point worth understanding. A separate counter row exists per entity and per period. A yearly scheme with two companies has two counter rows this year and two more next year.
The consequence is that periodic resets need no scheduled job and no year-end task. When the period changes, allocation simply lands on a different counter row, which starts at one. Nothing has to run at midnight on 1 January, and nothing can fail to run.
It also means the entities are genuinely independent. One company's invoice volume cannot advance another's sequence, which is what statutory numbering usually requires.
Choosing a period key
- Yearly — the common choice, and what most finance teams expect on documents.
- Monthly — for high volume, where a year's sequence would grow unwieldy.
- None — one continuous series for the life of the system.
Pick once, at setup. Changing the period key later restarts the sequence, so references issued afterwards can collide with historical ones unless the format also changed.
Setting up
- Create the scheme against the datastore and field.
- Set the prefix, format and padding.
- Choose the period key.
- Create the scheme for each entity that needs its own series.
- Create one record and check the reference reads as you intended.
Test with a throwaway record
Create one, look at the reference, then delete it. The gap it leaves is harmless, and it is far cheaper than discovering the format is wrong on the invoice a customer has already received.
Do not edit the next value casually
Moving the counter forwards is occasionally legitimate — continuing a series from a previous system, for instance. Moving it backwards means reissuing references that already exist, and the resulting duplicates are hard to unpick because both records look correct in isolation.
Worked example
A group with two trading companies sets up sales invoice numbering as {PREFIX}-{ENTITY}-{PERIOD}-{SEQ}, prefix INV, padding 5, period key yearly, with one scheme per entity. The first invoice of 2026 in the UK company is INV-GB-2026-00001; the Irish company's first is INV-IE-2026-00001 the same week. Neither affects the other, and 2027 starts again with no intervention.
Recommendations
- Decide the period key before go-live and leave it alone afterwards.
- One scheme per entity where entities are separate legal companies.
- Test with a throwaway record.
- Only ever move the counter forwards, and note why when you do.
When Numbers Are Assigned
A reference is allocated when the record is created. Not on approval, not on issue, not the first time somebody prints it.
Where to find it
Architect Panel → Data:
- Record Numbering — the counters and their current position
- Trash — where deleted records go — their numbers are not reused
Why at creation
Because everything that happens to a record afterwards needs something to refer to it by. An audit entry, a note, a linked document and an email to a customer all want a reference, and a record that has not got one yet forces every one of those to fall back to the internal ID.
Allocating later also creates an awkward window in which two people are looking at the same record and describing it differently.
Drafts consume numbers
This is the direct trade-off. A draft that is abandoned has already taken a number, and that number stays taken.
The alternative — allocating on approval — means the record is unreferenceable for as long as it is in progress, which is usually the period when people most need to discuss it. Consuming a number is the cheaper cost, but it is worth knowing about if your process creates many speculative records.
Deleted records keep their numbers
Deletion is a soft delete: the record moves to Trash and remains recoverable, so its reference must stay reserved. Reusing it would mean a restored record and a new one both claiming the same reference.
Imports
Imported records normally arrive carrying their own historical references, and those should be preserved — a customer's old invoice number does not become a different number because you changed system.
Afterwards, move the counter forwards past the highest imported value. If the import ends at 4,120 and the counter is still at 1, the next new record collides with an imported one. This is the single most common numbering mistake at go-live, and it surfaces weeks later when somebody notices two invoices with one number.
Check the counter after every bulk load
Not just the first. A second import from a different source can push the highest value up again.
References are not a security control
A sequential reference is guessable, so it must not be the only thing standing between somebody and a record. Access is enforced by security groups and row-level permissions; the reference is a label, not a key.
Worked example
A business migrating from a legacy system imports 4,120 invoices with their original numbers, then sets the counter's next value to 4,121. The first invoice raised in the new system is 4,121, so the series is continuous and no customer sees a number they have seen before. A later import of 300 credit notes prompts the same check against the credit note scheme.
Recommendations
- Preserve historical references on import.
- Advance the counter past the highest imported value, every time.
- Expect drafts to consume numbers and do not treat it as a fault.
- Never rely on a reference for access control.