Evidence ledger 24 sources Checked 27 Sep 2026

Evidence ledger

One row per claim in There is no neutral identifier: who published it, what grade it carries, when it was written, when the link was last checked, and the quote or figure it rests on. Nothing in the guide is cited from memory, so anything not in this table is not in the guide.

Topic: how production systems mint row and object identifiers, and how the choice fails (exhaustion, duplicate issuance, hotspots, leakage). Research date: 2026-09-27. All URLs fetched from this session's environment on 2026-09-27.

Network note: this session's egress policy allows github.com, gitlab.com, raw.githubusercontent.com and little else. Engineering-blog, paper and talk hosts (signalvnoise.com, instagram-engineering.com, github.blog, krebsonsecurity.com, postgresql.org, usenix.org, arxiv.org, youtube.com and others) are blocked, so this guide is built from repository artefacts: issues, merge requests, commits, specs, runbooks and the RFC working group's own repository. Accounts that exist only on blocked hosts are represented through the danluu/post-mortems collection entry that indexes them, and are labelled as such.

# Org Title Tier Published Checked URL Claim I take from it Supporting quote or figure
1 GitLab Tracking primary key integer overflow risk for ci_builds.id (#215017) adr 2020-04-20 2026-09-27 https://gitlab.com/gitlab-org/gitlab/-/issues/215017 GitLab noticed int4 exhaustion coming on its largest CI table and forecast the date "Primary key is an integer-typed sequence with results in a maximum number of 2,147,483,647 records"; as of 2021-04-10 max id 1.168 billion, "54.42%" of capacity; overflow forecast "between September 2021 (at a worst case scenario using an exponential forecast) and May 2022 (following a polynomial model)"
2 GitLab Add migration helpers for converting int columns to bigint (!49778) source 2020-12-11 (merged) 2026-09-27 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49778 The online int→bigint conversion is a dual-write: new column, sync trigger, batched backfill, no downtime Helper creates a bigint column with NOT NULL DEFAULT 0, "setup a trigger to keep the two columns in sync", schedules background jobs to backfill; "DOWNTIME = false"
3 GitLab Cleanup migration failure for p_ci_builds bigint conversion (#468671) source 2024-06 2026-09-27 https://gitlab.com/gitlab-org/gitlab/-/work_items/468671 The conversion programme begun in 2020 was still producing upgrade failures in 2024 "PG::DependentObjectsStillExist: ERROR" raised by cleanup_bigint_conversions_for_p_ci_builds in a 2k-reference upgrade test
4 GitLab The WebHook recent_failures counter may overflow (#330817) postmortem 2021-05-12 2026-09-27 https://gitlab.com/gitlab-org/gitlab/-/issues/330817 A production incident on GitLab.com from a smallint counter incremented without bound "32768 is out of range for ActiveModel::Type::Integer with limit 2 bytes" from WebHookWorkers; "hook.update!(recent_failures: hook.recent_failures + 1)"; incident tracked at gl-infra/production#4589
5 GitLab PG::UniqueViolation on index_issues_on_project_id_and_iid (#229614) postmortem 2020-07-16 2026-09-27 https://gitlab.com/gitlab-org/gitlab/-/issues/229614 Application-level ID allocation (per-project iid) collides under concurrent import "duplicate key value violates unique constraint 'index_issues_on_project_id_and_iid'"; race during long-running imports, "restore is somehow finding duplicates"; production Sentry exception referenced
6 GitLab Runbook: Patroni log analysis, duplicate key errors source checked 2026-09 (living doc) 2026-09-27 https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/patroni/log_analysis.md Operators see duplicate-key storms when a sequence is reset or lags a failover duplicate key "can [be] because of a sequence (implemented for serial columns) has been modified (i.e. has been RESET)"; remediation setval() above max, or ON CONFLICT
7 Nextcloud Some columns in the database are missing a conversion to big int (#13704) source 2019-01-20 2026-09-27 https://github.com/nextcloud/server/issues/13704 Widening ships as opt-in because the rewrite is too slow to run in an upgrade "Due to the fact that changing column types on big tables could take some time they were not changed automatically"; occ db:convert-filecache-bigint "needs to be made while the instance is offline"; columns include filecache.fileid, storages.numeric_id
8 Nextcloud Admin manual: bigint identifiers vendor living doc 2026-09-27 https://raw.githubusercontent.com/nextcloud/documentation/master/admin_manual/configuration_database/bigint_identifiers.rst The official cost statement for widening a live table "Changing columns in large tables can take several hours or even days, depending on the number of files in the Nextcloud instance"; advises shutting down the web server or maintenance mode
9 Nextcloud fileid numeric value out of range (files_antivirus #697) postmortem 2026-08-26 2026-09-27 https://github.com/nextcloud/files_antivirus/issues/697 An operator hit int exhaustion in production via a foreign column that lagged the primary's widening "SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'fileid' at row 1"; oc_files_antivirus.fileid was int(10) unsigned while oc_filecache.fileid is BIGINT
10 danluu/post-mortems (collection) Basecamp, GitHub, Strava exhaustion entries postmortem entries 2014–2021 2026-09-27 https://raw.githubusercontent.com/danluu/post-mortems/master/README.md Three named exhaustion outages: Basecamp Nov 2018 read-only; GitHub May 2021 scoped-tokens FK at max INT32, 9h48m of failures; Strava 2014-07-29 signed-int PK, uploads failed "In November 2018 a database hit the integer limit, leaving the service in read-only mode" (Basecamp); "A foreign key on the scoped-tokens table hit max INT32, causing high failure rates for Actions and Pages ... for 9h48m" (GitHub); "Hit the signed integer limit on a primary key, causing uploads to fail" (Strava). Primary write-ups sit on hosts this session cannot reach; claims are taken from the collection's entries.
11 Twitter snowflake (snowflake-2010 branch) README source 2010 2026-09-27 https://github.com/twitter-archive/snowflake/tree/snowflake-2010 The requirements and the clock posture of the archetypal node-local generator "There is no sequential id generation facility in Cassandra, nor should there be"; minimum 10k ids/sec/process, <2ms; k-sorted within ~"1 second" bound; "If your clock is running fast and NTP tells it to repeat a few milliseconds, snowflake will refuse to generate ids until a time that is after the last time we generated an id"
12 Sony sonyflake README source 2015 (repo) 2026-09-27 https://github.com/sony/sonyflake The bit budget is a three-way trade; Sony re-cut Snowflake's fields "39 bits for time in units of 10 msec, 8 bits for a sequence number, 16 bits for a machine id"; lifetime "174 years" vs Snowflake's 69; works on "2^16" machines vs 2^10; at most "2^8 IDs per 10 msec" per instance
13 Segment (Twilio) ksuid README source 2017 2026-09-27 https://github.com/segmentio/ksuid 160-bit k-sortable IDs: pay 96 extra bits to drop worker coordination 20 bytes: 32-bit big-endian timestamp + "128 bits of pseudorandom data", "64 times larger than the 122 bits" of UUIDv4; epoch "adjusted to May 13th, 2014, providing over 100 years of life"; base62 text is 27 chars and lexicographically sortable
14 ULID project ulid/spec README source 2016 2026-09-27 https://github.com/ulid/spec The monotonicity contract and its stated failure mode UUIDv4 "provides no other information than randomness which can cause fragmentation in many data structures"; 48-bit ms timestamp "valid until 10889 AD" + 80 random bits; same-millisecond generation increments "the random component ... by 1 bit in the least significant bit position (with carrying)"; on 2^80 overflow "the generation will fail"
15 Mastodon Non-serial ("snowflake") IDs (PR #4801) adr merged 2017-10-04 2026-09-27 https://github.com/mastodon/mastodon/pull/4801 A recorded argument for abandoning sequential IDs, on privacy grounds, with dissent aschmitz: "My motivation is purely to hide the total number of entries in each table"; nightpool: "This seems like a huge change for no perceivable benefit to >90% of instances"; layout: top 6 bytes ms-resolution time, bottom 2 bytes sequence; IDs returned as strings to protect JavaScript clients from 64-bit precision loss
16 IETF uuidrev WG rfc4122bis working repository adr published as RFC 9562, 2024-05 2026-09-27 https://github.com/ietf-wg-uuidrev/rfc4122bis The UUID revision was developed in public, on GitHub, and obsoletes RFC 4122 "RFC 9562 - Universally Unique IDentifiers (UUIDs)", May 2024, "Obsoletes: RFC 4122"; repo is "the working area for the IETF UUIDREV Working Group Internet-Draft"
17 IETF uuidrev WG draft-ietf-uuidrev-rfc4122bis (full text) adr 2024 2026-09-27 https://raw.githubusercontent.com/ietf-wg-uuidrev/rfc4122bis/main/draft-ietf-uuidrev-rfc4122bis.md UUIDv7 exists because random UUIDs thrash database indexes; the spec claims an order-of-magnitude locality gap "Time ordered monotonic UUIDs benefit from greater database index locality"; "the real-world differences in this approach of index locality vs random data inserts can be one order of magnitude or more"
18 IETF uuidrev WG same document, monotonicity methods adr 2024 2026-09-27 https://raw.githubusercontent.com/ietf-wg-uuidrev/rfc4122bis/main/draft-ietf-uuidrev-rfc4122bis.md The spec standardises three ways to keep same-millisecond IDs ordered Method 1 "fixed bit-length counter ... MUST be positioned immediately after the embedded timestamp"; Method 2 monotonic random "incremented in the least significant position"; Method 3 sub-millisecond precision "substitute for up to 12 random bits immediately following the timestamp"
19 IETF uuidrev WG same document, security and background adr 2024 2026-09-27 https://raw.githubusercontent.com/ietf-wg-uuidrev/rfc4122bis/main/draft-ietf-uuidrev-rfc4122bis.md IDs are not credentials, and the RFC exists because industry forked first "Implementations SHOULD NOT assume that UUIDs are hard to guess. For example, they MUST NOT be used as security capabilities"; UUIDv1 timestamp epoch "uncommon and difficult to represent"; MAC addresses "SHOULD NOT be used within a UUID"; background catalogues ~16 non-standard schemes (ULID, KSUID, Snowflake, Sonyflake, ObjectID, ...) built "to solve the problem of creating a better time-based, sortable unique identifier for use as a database key"
20 PostgreSQL commit 78c5e141: Add UUID version 7 generation function source 2024-12-11 2026-09-27 https://github.com/postgres/postgres/commit/78c5e141e9c139fc2ff36a220334e4aa25e1b0eb Postgres implements RFC 9562 method 3 and survives backwards clocks inside one backend uuidv7() per RFC 9562; "the 12-bit sub-millisecond timestamp fraction is stored immediately after the timestamp, in the space referred to as 'rand_a'", guaranteeing monotonic generation "within the same backend even when the system clock goes backward"
21 2ndQuadrant / Tomas Vondra tvondra/sequential-uuids README source 2018 2026-09-27 https://github.com/tvondra/sequential-uuids Why random UUIDs thrash a B-tree, and a wrap-around design that limits the damage "Regular random UUIDs are distributed uniformly over the whole range of possible values. This results in poor locality when inserting data into indexes - all index leaf pages are equally likely to be hit, forcing the whole index into memory"; generators wrap (256-value blocks / 60s intervals over 65,536 blocks)
22 Rails PR #26266: Change default primary keys to BIGINT source merged 2016-12 2026-09-27 https://github.com/rails/rails/pull/26266 The framework-level fix for exhaustion: change the default before apps need it Opens with "Friends don't let friends use INT as a primary key"; int→bigint default for PostgreSQL and MySQL in Rails 5.1; compatibility layer keeps pre-5.1 migrations producing integer
23 Rails PR #24962: bigserial pk by default (closed unmerged) source closed 2016-12-08 2026-09-27 https://github.com/rails/rails/pull/24962 The rejected first attempt, and why: same migration, different schema tenderlove: "Running the same migration on Rails 4 and Rails 5 will produce a different database schema"; rafaelfranca: a 5.0 schema loaded on 5.1 would "generate a different result"; closed "Fixed by #26266"
24 CockroachDB Issue #78049: use hash-sharded indexes by default adr 2022-03-17 2026-09-27 https://github.com/cockroachdb/cockroach/issues/78049 In a range-sharded store the ordered key is the problem, not the solution bdarnell: "Workloads involving sequential keys can have major performance problems on CockroachDB. Hash-sharded indexes alleviate this problem, but because they're not the default ... many users who would benefit from them do not know to use them"; cost: "hash-sharding an index does reduce scan performance (proportional to the number of buckets)"
25 stateless-me uuidv47 README source 2025 2026-09-27 https://github.com/stateless-me/uuidv47 The locality/leakage tension is real enough that people encrypt the timestamp "store sortable UUIDv7 in your database while emitting a UUIDv4-looking façade at your API boundary"; "XOR-masks only the UUIDv7 timestamp field with a keyed SipHash-2-4 stream"
26 CockroachDB Issue #39340: improve UX for hash-sharded indexes source 2019-08-05 2026-09-27 https://github.com/cockroachdb/cockroach/issues/39340 The workload behind the hotspot problem, and why the fix had to be cheap syntax an "INDEX (ts)" schema "would have a hot spot"; the manual computed-column workaround "is starting to get heavy"; proposal: "we shoulder the burden of hashing and installing a check constraint behind a new syntax"

Tier mix

postmortem 4 (rows 4, 5, 9, 10) · source 14 · adr 7 · vendor 1. No papers and no talks: the hosts that carry them (usenix.org, arxiv.org, youtube.com) are outside this session's network policy; the absence is stated in the guide.

Organisations represented

GitLab, Nextcloud, Twitter, Sony, Segment/Twilio, ULID project, Mastodon, IETF uuidrev WG, PostgreSQL, 2ndQuadrant, Rails core, CockroachDB, stateless-me, plus Basecamp, GitHub and Strava via the postmortem collection: 16.