Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Surrogate Key

A surrogate key is a primary key column with no meaning outside the database: it exists purely to identify a row, not to represent a business fact. An auto-increment integer, a UUID, or a ULID used as a primary key are all surrogate keys. They are opposed to natural keys, values such as an email address, a national ID, or an ISBN, that already have meaning in the domain and would otherwise be used to identify the row.

Surrogate keys are preferred in most schema because natural keys can change, can turn out not to be as unique as assumed, and are often composite or of variable length, all of which make joins and indexes slower and migrations riskier.

A related but distinct usage, common in APIs, is to add a second surrogate column purely for public exposure: the internal auto-increment integer stays the primary key and drives foreign-key relations, while a separate UUID, ULID, or an obfuscated value such as a Sqid is exposed in URLs and API responses. This keeps the compact integer for indexing while avoiding the enumeration and information-leak risks of publishing sequential IDs.

<?php

    // Doctrine migration: surrogate primary key plus a public-facing surrogate column
    $table->addColumn('id', 'integer', ['autoincrement' => true]);
    $table->setPrimaryKey(['id']);
    $table->addColumn('public_id', 'guid'); // exposed in the API instead of 'id'

?>

Documentation

See Also