$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[December 23, 2025] Eloquent ORM

Eloquent Key Type: UUID Primary Keys

Eloquent Key Type: UUID Primary Keys

────────────────────────────────────────────────────────

Eloquent Key Type: UUID Primary Keys

Tip: UUID Primary Key

protected $keyType = 'string';
public $incrementing = false;

protected static function booted(): void
{
    static::creating(fn($model) => $model->id = Str::uuid());
}

Gotcha: Relations Need Key Type Match

If the parent uses UUID, the foreign key on the child must also be a string/UUID type.

Tip: Str::orderedUuid() for Indexing

Str::orderedUuid();

Generates UUIDs that sort chronologically. Better for database indexing.

Gotcha: Pagination with UUIDs

Cursor pagination doesn't work well with UUIDs. Use offset pagination instead.

Tip: Migration for UUID

$table->uuid('id')->primary();

Not $table->id() — that creates a big integer.

Gotcha: Route Model Binding with UUIDs

Laravel auto-detects the key type. But if you use getRouteKeyName(), make sure it returns the UUID column.

Tip: Use cursor() for Memory-Neutral Iteration

When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.

Tip: whereHas() vs load() — Two Different Things

whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.

Gotcha: withCount() Adds a Subquery

withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.

Senior Insight

UUID or ULID primary keys have advantages for distributed systems, but they kill database performance at scale. UUIDv4 is random, causing index fragmentation on B-tree indexes. I use UUIDv7 (time-ordered) or ULID for primary keys when I need distributed ID generation. And I never use UUIDs as the primary key in pivot tables — the index size alone can slow joins significantly.

Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)

────────────────────────────────────────────────────────
<-- back to posts