Why the format of a document number matters
A document number's only real job is to be unique, but a well-designed one does far more than that. It tells you, at a glance, roughly when a document was issued, which part of the business it came from, and whether anything is missing from the sequence. A poorly designed one — random digits, inconsistent lengths, or numbers that reset without warning — creates work for whoever has to reconcile the books later.
The three most common documents that need this treatment are invoices, receipts, and purchase orders. Each has slightly different conventions, but they share the same underlying structure.
The anatomy of a good document number
Most professional numbering formats are built from up to four parts, in this order:
- Prefix — identifies the document type (INV, RCT, PO)
- Context code (optional) — a client, department, vendor, or store code
- Date component (optional) — usually year, or year and month
- Sequential number — a zero-padded counter that never repeats or resets unexpectedly
For example: INV-2026-0001 breaks down as document type, year, and sequence. PO-PROC-000045 breaks down as document type, department code, and sequence.
Invoice numbering
Invoice numbers are the most tightly scrutinized of the three, since they're often required for tax filings. In most jurisdictions, invoice numbers need to be sequential with no gaps — skipping a number can raise questions during an audit, even if the transaction was simply cancelled.
Common patterns:
- INV-2026-0001
- 2026-Q1-INV-001
- CLI004-INV-0001 (client-coded)
If you cancel an invoice, it's generally better practice to keep the number and mark it "void" than to delete it and let a later invoice reuse the number.
Receipt numbering
Receipts are usually generated at higher volume and lower individual value than invoices, so the priority shifts slightly — from strict legal compliance toward fast lookup and refund matching. A store or register code is especially useful here if you operate more than one point of sale.
- RCT-000123
- STORE04-000123
- 2026-0304-000123 (date + sequence)
Purchase order numbering
PO numbers exist mainly to connect three documents: the order itself, the vendor's invoice, and the goods receipt. This "three-way match" is a standard accounts-payable control, and it only works cleanly if the PO number is unique and referenced consistently by the vendor.
- PO-2026-0001
- PO-PROC-000045 (department-coded)
- PO-VEND22-0012 (vendor-coded)
Implementing auto-incrementing numbers in code
If you're building numbering into an application rather than generating it manually, the core idea is the same across languages: store the last-used number, increment it, and pad it to a fixed width.
Python example:
def next_invoice_number(last_number, prefix="INV", digits=4):
n = last_number + 1
return f"{prefix}-{str(n).zfill(digits)}", n
PHP example:
function nextInvoiceNumber($lastNumber, $prefix = "INV", $digits = 4) {
$n = $lastNumber + 1;
return $prefix . "-" . str_pad($n, $digits, "0", STR_PAD_LEFT);
}
In both cases, the important part isn't the code — it's making sure "last_number" is read and written atomically (e.g. inside a database transaction) so two invoices created at the same moment never collide.
Common mistakes to avoid
- Inconsistent digit padding — mixing INV-1 with INV-0002 breaks alphabetical sorting.
- Reusing numbers after deletion — always void, never delete-and-reuse.
- Resetting sequences without a date anchor — if you reset yearly, put the year in the number itself so two "INV-0001"s from different years don't collide in your records.
- Manually typing numbers — even a simple generator (like the ones below) removes the risk of typos and accidental duplicates.