Expert guide
Access AutoNumber Gaps and Reset: What to Do (and Not Do)
AutoNumber is for uniqueness. Sequential document numbers need their own design.
Call us at +1 (385) 386-3860
Short answer: AutoNumber gaps are normal: values are consumed by cancelled new records, deletions and failed appends. Use AutoNumber only as an internal primary key and never show it as an invoice or order number. To reset an empty table's seed, compact; to set the next value, use ALTER TABLE ... ALTER COLUMN ID COUNTER(start, 1). For gap-free, formatted document numbers, use a counter table incremented when the document is finalised. This is standard in our Access database design work.
A user notices invoice 1047 is followed by 1049 and asks where 1048 went. In many Access databases the answer is that the invoice number is an AutoNumber, and someone started a new invoice and pressed Escape. Auditors and customers dislike gaps in invoice sequences, and the fix is not to fight AutoNumber but to stop using it for something it was never designed to do.
How AutoNumber Really Works
The next value is allocated as soon as a new record is started (the first keystroke on a new row), not when it is saved.
If the new record is cancelled, that value is gone.
Deleting records never frees their numbers.
An append query that fails part way can consume values for rows never written.
Values are unique within the table; that is the only promise.
Resetting the Seed
Empty table: compact
After deleting all rows from a table (for example a test or staging table), Compact and Repair resets the AutoNumber so the next record starts at 1.
Set a specific next value
ALTER TABLE tblOrders ALTER COLUMN OrderID COUNTER(10000, 1);
Run it as a data-definition query or with CurrentDb.Execute. The first number is the next seed, the second the increment. Never set it lower than the current maximum, or new records will collide with existing keys. Back up first, and do it with nobody else in the database.
Fix a seed that went wrong
Occasionally, after importing or corruption, the seed falls below existing values and new records fail with duplicate key errors. Find the maximum (DMax), then set the seed to max + 1 with ALTER COLUMN COUNTER.
Why Not to Renumber Existing Records
Primary keys are referenced by child tables; renumbering breaks relationships or requires cascading updates.
Numbers printed on documents, emails and external systems would no longer match.
There is no business benefit: users should not see AutoNumbers at all.
Gap-Free Document Numbers: The Counter Table
tblCounters: CounterName (PK, Text), Year (Number), LastValue (Number)
Public Function NextNumber(ByVal counterName As String) As String
Dim ws As DAO.Workspace, db As DAO.Database, rs As DAO.Recordset
Dim yr As Integer, n As Long, tries As Integer
yr = Year(Date)
Set ws = DBEngine.Workspaces(0): Set db = CurrentDb
Retry:
On Error GoTo Locked
ws.BeginTrans
Set rs = db.OpenRecordset("SELECT * FROM tblCounters WHERE CounterName='" & _
counterName & "'", dbOpenDynaset)
rs.Edit
If rs!Year <> yr Then rs!Year = yr: rs!LastValue = 0 ' restart each year
rs!LastValue = rs!LastValue + 1
n = rs!LastValue
rs.Update
ws.CommitTrans
rs.Close
NextNumber = "INV-" & yr & "-" & Format(n, "0000") ' e.g. INV-2026-0042
Exit Function
Locked:
ws.Rollback
tries = tries + 1
If tries < 10 Then
Dim t As Single: t = Timer: Do While Timer < t + 0.2: DoEvents: Loop
Resume Retry
End If
Err.Raise vbObjectError + 1, , "Could not get the next number: " & Err.Description
End FunctionCall NextNumber when the invoice is posted or finalised, not when the draft is created.
Store the result in a separate InvoiceNo field with a unique index.
Keep the AutoNumber InvoiceID as the internal key for relationships.
If an issued number must be cancelled, void the document instead of deleting it, so the sequence stays complete.
Why Not DMax + 1?
| Approach | Multi-user safe | Gap-free | Notes |
|---|---|---|---|
| AutoNumber shown to users | Yes | No | Gaps from cancelled records |
| DMax(...) + 1 on form open | No | Mostly | Two users can get the same number |
| DMax + 1 at save with unique index and retry | Mostly | Yes | Acceptable for low volume |
| Counter table in a transaction (above) | Yes | Yes | Recommended; supports yearly reset and prefixes |
SQL Server Back Ends
With SQL Server, identity columns behave like AutoNumber (gaps are normal), and SEQUENCE objects or a counter table with locking provide document numbers. Plan this during migration; see AI-assisted Access to SQL Server migration. For an invoicing database built this way, see our Access invoice and payment tracker.
FAQ
Access AutoNumber FAQ
Gaps, resets and invoice numbers