Sequences
A sequence field auto-fills a formatted running number — INV-2025-000042, SKU-07 — on insert.
The number is assigned by a per-entity database trigger, set-based over the whole inserted batch, so
it stays correct and contention-safe even under bulk inserts and imports.
Declaring a sequence field
Section titled “Declaring a sequence field”Add a <Sequence> field to the entity with a Format template. See
Entities → Field types.
<Sequence Name="Sku" Format="SKU-#2" /><Sequence Name="InvoiceNo" Format="INV-{yy}-#6" Scope="Invoice" />The format template
Section titled “The format template”The template mixes literal text, placeholder tokens, and a sequence marker:
#N— the running number, zero-padded to widthN(e.g.#6→000042).- A bare
#(no digits) defaults to width 2 — this default lives in exactly one place, the sharedFormatSequenceNumberfunction. - Date tokens (
{yy},{yyyy},{MM}, …) and record-field placeholders (e.g.{Region},{Region:initials}) are “cooked” from the record context before the number is applied.
How assignment works
Section titled “How assignment works”At submit time the engine cooks the template and produces a pipe-delimited token the trigger consumes:
ResourceName | CookedTemplate | CompanyId | GuidKeye.g. Invoice | INV-25-#6 | 1 | AB12CD3The per-entity AFTER-INSERT trigger (installed by SequenceNumberSqlHandlerService from the entity
migration) then, set-based for the whole batch:
- groups the inserted rows by
(Format, ScopeKey)whereScopeKey = "{CompanyId}|{ResourceName}"; - reserves one contiguous block per group by advancing a counter in
[Genie].[SequenceNumbers]; - assigns each row its number with
ROW_NUMBER()and formats it via the shared[Genie].[FormatSequenceNumber](SQL Server) /"Genie".format_sequence_number(PostgreSQL) function.
Those shared helper functions are deployed once at startup by the SequenceSqlContributor; the trigger
itself is per-entity because it lives with the entity’s table. Both dialects are supported.
Previewing the next number
Section titled “Previewing the next number”A form can show the user the next value before saving:
| Method | Route | Returns |
|---|---|---|
POST |
/api/v1/genie/object/sequence-number |
SuccessDataResult<string> — the previewed number |
This calls a read-only preview function (GetSequenceNumberPreview / get_sequence_number_preview)
that peeks at the counter + 1 without consuming it. See
Object endpoints.
Sequences in imports
Section titled “Sequences in imports”Sequence tokens are also available to the import pipeline through the Sequence(...) expression, so
generated values (e.g. an SKU) can be produced during a bulk import while still respecting a
hand-entered value:
Sequence('SKU-#2','Product','@SessionCompanyId','@Guid[7]')See Import → expressions for the full signature.