diff --git a/content/docs/data-modeling/field-types.mdx b/content/docs/data-modeling/field-types.mdx index 2a9438337b..d5eb9f9182 100644 --- a/content/docs/data-modeling/field-types.mdx +++ b/content/docs/data-modeling/field-types.mdx @@ -483,6 +483,21 @@ Auto-incrementing number with format template. { name: 'ticket_number', label: 'Ticket #', type: 'autonumber', autonumberFormat: 'TKT-{0000}' } ``` + +**An autonumber is unique and monotonic per scope — it is not gapless.** Any +write that gets rejected after the number was reserved — a unique violation on +another field, a failed validation rule, a `beforeInsert` hook that throws — +still consumes that number, and it is never reissued. `TKT-0001` succeeding and +`TKT-0002` failing means the next row is `TKT-0003`; `TKT-0002` will not exist. + +This is a decided property of the counter, not a bug to work around. If you are +building an invoice, contract, or receipt sequence on an `autonumber` field, +design for gaps: an autonumber guarantees a unique, ever-increasing business +identifier, but it is **not** a legally gapless document number. Treat that +guarantee as a separate requirement to satisfy explicitly, not something +`autonumber` already gives you. + + --- ## Embedded Structured Types diff --git a/content/docs/data-modeling/schema-design.mdx b/content/docs/data-modeling/schema-design.mdx index 9ad5025117..15b333f210 100644 --- a/content/docs/data-modeling/schema-design.mdx +++ b/content/docs/data-modeling/schema-design.mdx @@ -218,6 +218,13 @@ Field.autonumber({ // no separate reset config. A fixed prefix like 'INV-{000}' keeps one global counter. ``` +The counter is unique and monotonic per scope, **not gapless** — a rejected +write (a unique violation on another field, a failed validation rule, a +throwing `beforeInsert`) still consumes the number it reserved. Before wiring +an `autonumber` field to an invoice, contract, or receipt sequence, see the +[full contract](/docs/data-modeling/field-types#autonumber) in the Field Type +Gallery. + ### User Fields Pick a person — the equivalent of Airtable's *Collaborator* or Salesforce's