Skip to content

Storage and Allocation

AstorisTheBrave edited this page Aug 30, 2026 · 1 revision

Storage and allocation

Production-safe human references require state. The canonical model is:

entity table                 reference table
MID primary key  <---------  namespace + REF unique key

Recommended storage responsibilities

  • Store the MID as the entity's canonical primary key, preferably as a native UUID or 16-byte value.
  • Derive the PID from the MID and namespace unless a measured query pattern justifies indexing it.
  • Store each REF as a unique value mapped to its MID and namespace.
  • Keep retired namespace definitions available for historical parsing.
  • Never use an in-memory uniqueness check as a production allocation boundary across processes.

Random references

A random REF candidate is not allocated until storage accepts it:

  1. Generate a payload using a cryptographically secure source and unbiased sampling.
  2. Format the prefix, payload groups, and modulo-37 check symbol.
  3. Attempt one atomic insert backed by a unique constraint.
  4. Return success only after the insert commits.
  5. On conflict, generate a new candidate and retry within a documented bound.
  6. Return allocation_exhausted when the bound is reached.

The TypeScript ReferenceStore.reserve boundary represents that atomic insert-or-conflict operation.

Sequential references

Sequential references require a transaction that:

  1. locks or atomically advances the namespace-and-scope counter;
  2. verifies that the fixed width is not exhausted;
  3. binds the allocated value to the supplied MID; and
  4. commits both changes together.

Calendar-year scopes use the UTC year. Sequential values reveal volume and ordering, so applications should choose this strategy deliberately.

Resolving a disputed order

When Alice enters Bob's ORD-… reference, the application should:

  1. normalize it against the active namespace registry;
  2. reject invalid length, symbols, or checksum;
  3. query the REF mapping table;
  4. treat no matching row as “not found,” not as a parsing error;
  5. load the entity by the returned MID; and
  6. run normal authorization before displaying it.

The PID may be derived from the MID for an API response or diagnostic event, but REF resolution does not require an intermediate PID.

PostgreSQL integration

The repository provides reversible migrations and tested functions:

  • identifold_reserve_reference for atomic random reservation;
  • identifold_allocate_sequence for scoped transactional allocation; and
  • TypeScript adapters for direct PostgreSQL, Prisma, and Drizzle clients.

Apply the migration:

psql "$DATABASE_URL" --set ON_ERROR_STOP=1 --file integrations/postgres/migrations/001_identifold.up.sql

See the PostgreSQL integration guide. Hosted PostgreSQL 18 tests cover concurrency, allocation ordering, client adapters, and reversible migrations.

Clone this wiki locally