Chapter 04 · Schema Design, Keys, Constraints, Sequences, and Temporal Features

IDENTITY, SEQUENCE, GUID Strategies, Ordered IDs, and Hot-Page Considerations

Choose IDENTITY, SEQUENCE and GUID strategies from allocation scope, rollback/gap behavior, index shape, concurrency and privacy needs rather than folklore.

Intermediate100–130 minutesIdentifier allocation + metadata labSQL Server 2025 · sequence/GUID stable featuresDeveloper/Express · no paid topology requiredLast reviewed: August 2026

Learning outcomes

ServiceHub needs identifiers for work orders, public API requests, and legally significant invoice numbers. One engineer proposes IDENTITY for all three because it “always gives the next number.” Another wants random GUIDs everywhere because they are globally unique. A third asks for a SEQUENCE so multiple tables can share a range. Each mechanism solves a different problem, and none promises a gap-free business sequence.

01

Compare IDENTITY, SEQUENCE and uniqueidentifier generation by scope, timing, transaction behavior and storage/index consequences.

02

Demonstrate that identity and sequence values can be skipped or consumed when transactions roll back.

03

Explain sequence caching and why NO CACHE reduces but does not eliminate possible gaps.

04

Compare NEWID and NEWSEQUENTIALID tradeoffs, including key width, page locality and predictability concerns.

05

Recognize last-page insert contention as a measured concurrency problem and use OPTIMIZE_FOR_SEQUENTIAL_KEY only when evidence supports it.

Business-number rule

Surrogate keys are technical identifiers. If regulations or business processes require a separately governed document number with special gap, allocation, cancellation, reconciliation, or audit rules, design that process explicitly. Do not infer those guarantees from IDENTITY or SEQUENCE.

1. IDENTITY is table-column generation, not a transactional counter

An IDENTITY(seed, increment) property belongs to one table column. SQL Server generates a value during insert. The property does not enforce uniqueness by itself; uniqueness normally comes from a PRIMARY KEY or UNIQUE constraint. Identity values can have gaps because failed/rolled-back inserts and internal caching do not promise reuse.

sql · observe an identity gap after rollback
USE ServiceHubLab;GOIF SCHEMA_ID(N'lab04') IS NULL EXEC(N'CREATE SCHEMA lab04 AUTHORIZATION dbo;');GODROP TABLE IF EXISTS lab04.IdentityProbe;CREATE TABLE lab04.IdentityProbe(    id bigint IDENTITY(1000,1) NOT NULL CONSTRAINT PK_IdentityProbe PRIMARY KEY,    note varchar(40) NOT NULL);GOINSERT lab04.IdentityProbe(note) VALUES ('committed-1');BEGIN TRANSACTION;INSERT lab04.IdentityProbe(note) VALUES ('rolled-back');SELECT SCOPE_IDENTITY() AS allocated_inside_transaction;ROLLBACK;INSERT lab04.IdentityProbe(note) VALUES ('committed-2');GOSELECT * FROM lab04.IdentityProbe ORDER BY id;SELECT IDENT_CURRENT(N'lab04.IdentityProbe') AS current_identity_value;GO

You should see a missing identifier for the rolled-back insert. That is normal. SCOPE_IDENTITY() is generally safer than session/global identity functions when you need the value generated by your own insert scope, but the broader lesson is that generated numeric IDs are not a receipt ledger.

2. SEQUENCE is a schema object that can serve multiple consumers

A SEQUENCE is independent of a table. Code can request NEXT VALUE FOR before or during an insert, and several tables can use the same sequence. This flexibility is useful for coordinated technical numbering, but values are generated outside the transaction that consumes them. Microsoft explicitly documents that rollback does not give a sequence value back.

sql · sequence allocation survives rollback
USE ServiceHubLab;GODROP SEQUENCE IF EXISTS lab04.DispatchSequence;GOCREATE SEQUENCE lab04.DispatchSequence    AS bigint    START WITH 50000    INCREMENT BY 1    CACHE 20;GOSELECT NEXT VALUE FOR lab04.DispatchSequence AS first_value;GOBEGIN TRANSACTION;SELECT NEXT VALUE FOR lab04.DispatchSequence AS rolled_back_value;ROLLBACK;GOSELECT NEXT VALUE FOR lab04.DispatchSequence AS next_after_rollback;GOSELECT name, current_value, cache_size, is_cachedFROM sys.sequencesWHERE object_id = OBJECT_ID(N'lab04.DispatchSequence');GO

The sequence advances regardless of transaction outcome. With CACHE, an unexpected shutdown can also lose unused cached numbers. NO CACHE persists each current value more often but still cannot make sequence usage gap-free because applications can request values and never commit or use them.

3. GUIDs trade compactness and locality for decentralized uniqueness

uniqueidentifier stores a 16-byte GUID. NEWID() generates values without an increasing key pattern, which is convenient for distributed generation but can create random insertion patterns when used as the leading clustered key. Wider clustering keys also propagate into nonclustered index row locators, increasing storage. These costs do not make GUIDs “bad”; they mean physical design must match the workload.

NEWSEQUENTIALID() can reduce random leaf-level insert behavior when used as a DEFAULT on a uniqueidentifier column. Microsoft warns that its values are predictable enough to be unsuitable when predictability exposes sensitive resources, and sequential clusters can shift after restart/failover/movement. It is not a cryptographic secret or a portable monotonic clock.

sql · compare GUID defaults and metadata
USE ServiceHubLab;GODROP TABLE IF EXISTS lab04.GuidProbe;CREATE TABLE lab04.GuidProbe(    guid_id uniqueidentifier NOT NULL        CONSTRAINT DF_GuidProbe_Id DEFAULT NEWSEQUENTIALID(),    external_token uniqueidentifier NOT NULL        CONSTRAINT DF_GuidProbe_Token DEFAULT NEWID(),    note varchar(40) NOT NULL,    CONSTRAINT PK_GuidProbe PRIMARY KEY CLUSTERED (guid_id));GOINSERT lab04.GuidProbe(note) VALUES ('one'),('two'),('three');SELECT guid_id, external_token, noteFROM lab04.GuidProbeORDER BY guid_id;GO

This tiny lab cannot prove fragmentation or throughput. Those are workload properties that require enough rows, concurrency, cache context, and storage observations. The lesson intentionally avoids fake performance numbers.

4. Sequential keys can create a hot last page under concurrency

Ascending identities and other ever-increasing clustered keys usually insert at the right edge of a B+ tree. Under high concurrent insert rates, many workers can contend for the same final page, often visible as PAGELATCH_EX waits. SQL Server 2019 and later provides OPTIMIZE_FOR_SEQUENTIAL_KEY, an index option designed for last-page insert contention.

Do not enable it merely because a table has an IDENTITY column. First verify that the clustered/index leading key is sequential, the workload is highly concurrent, and latch evidence points to last-page contention. The option changes throughput/fairness behavior; it is not a universal “identity performance switch.”

sql · inspect whether an index uses sequential-key optimization
USE ServiceHubLab;GOSELECT OBJECT_SCHEMA_NAME(i.object_id) AS schema_name,       OBJECT_NAME(i.object_id) AS table_name,       i.name AS index_name,       i.optimize_for_sequential_keyFROM sys.indexes AS iWHERE i.object_id IN (OBJECT_ID(N'ops.WorkOrder'), OBJECT_ID(N'lab04.IdentityProbe'))  AND i.index_id > 0;GO

A zero here proves only that the option is currently off. It does not prove contention exists or does not exist. Later observability/performance chapters use waits, latch evidence, workload concurrency, and measured throughput to make that decision.

5. Deliberately wrong approach: promise gap-free invoice numbers with IDENTITY

A billing table uses IDENTITY as the legal invoice number and a report flags any missing number as fraud. A transaction rolls back after identity allocation, producing a gap. The database behaved correctly; the design attached a business guarantee to a mechanism that never promised it.

Diagnosis

Separate surrogate key generation from the business numbering policy. IDENTITY and SEQUENCE optimize technical allocation; both can produce gaps. Sequence caching can add additional gaps after abnormal shutdown.

Repair

Keep a stable surrogate key for relational identity. If the business requires a controlled document-number lifecycle, define allocation, reservation, cancellation, retry, reconciliation, and audit semantics explicitly. That may require serialized/gated business logic and should be reviewed for concurrency and availability tradeoffs.

6. Hands-on lab: compare allocation semantics

sql · capture allocation evidence
USE ServiceHubLab;GOSELECT    OBJECT_SCHEMA_NAME(ic.object_id) AS schema_name,    OBJECT_NAME(ic.object_id) AS table_name,    c.name AS identity_column,    ic.seed_value,    ic.increment_value,    ic.last_valueFROM sys.identity_columns AS icJOIN sys.columns AS c  ON c.object_id = ic.object_id AND c.column_id = ic.column_idWHERE ic.object_id = OBJECT_ID(N'lab04.IdentityProbe');SELECT name, start_value, increment, current_value, cache_size, is_cachedFROM sys.sequencesWHERE object_id = OBJECT_ID(N'lab04.DispatchSequence');GO

Verification checklist

  • You observed an IDENTITY value not reused after rollback.
  • You observed a SEQUENCE value consumed outside transaction rollback.
  • You can explain why CACHE and NO CACHE do not create a gap-free guarantee.
  • You can explain the locality/width/predictability tradeoffs of GUID strategies.
  • You did not infer last-page contention from key shape alone; you treated it as a measured concurrency problem.
sql · cleanup identifier probes
USE ServiceHubLab;GODROP TABLE IF EXISTS lab04.GuidProbe;DROP TABLE IF EXISTS lab04.IdentityProbe;DROP SEQUENCE IF EXISTS lab04.DispatchSequence;GO

7. Production judgment and next bridge

Choose key generation based on scope, distribution, storage, concurrency, exposure, and business semantics. Small increasing numeric keys are compact and cache-friendly but can concentrate inserts. Random GUIDs decentralize generation but widen indexes and randomize placement. Sequential GUIDs improve locality but are not private unpredictable tokens. Sequences coordinate multiple consumers but are intentionally decoupled from transaction rollback. An additional operational concern is recovery and replay: after restores, failovers, retries, or message redelivery, application logic must rely on enforced uniqueness/idempotency rules rather than assuming a generated value reveals commit order or business chronology. Identity/sequence metadata is allocation state, not a durable event ledger.

Lesson 4 keeps the schema doing useful work without duplicating expressions in every query. Computed columns can centralize deterministic transformations and can even become indexed access paths—but only when determinism, precision, ownership, data types, and SET-option requirements are satisfied.

Check your understanding

  1. Does IDENTITY guarantee gap-free numbering?
  2. Why can a SEQUENCE have gaps after rollback even with NO CACHE?
  3. When is NEWSEQUENTIALID preferable to NEWID, and what warning comes with it?
  4. What symptom can indicate last-page insert contention?
  5. When should OPTIMIZE_FOR_SEQUENTIAL_KEY be considered?
Review the answers

No. Failed/rolled-back inserts and caching can leave gaps; uniqueness also requires a key/unique constraint.

Sequence values are allocated outside the transaction and can be requested without ever being committed/used.

It can improve insert locality for GUID-keyed indexes, but values are more predictable and can form new clusters after restart/failover/movement.

Under the right workload, concurrent inserts can accumulate PAGELATCH_EX waits on the last page of a sequential index.

Only after measured evidence shows sequential-key last-page contention in a high-concurrency workload; it is not a default tuning rule.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.