ADR 0001: Internal UUIDs vs. external ids

Status:

Accepted

Context

GAME must address records both in its own URLs and through the integrator’s domain keys, without coupling the two namespaces. If GAME exposed the integrator’s keys as primary keys (or vice versa), a rename on either side would ripple across the boundary.

Decision

Every table’s primary key is an internal UUID (app/model/base_model.py). Entities additionally carry a caller-owned external string: externalGameId (app/model/games.py, globally unique), externalTaskId (app/model/tasks.py, unique per game, not globally), and externalUserId (app/model/users.py, globally unique). Internal ids appear in URLs that address a specific record (/games/{gameId}/...); external ids are how callers reference tasks and users thereafter.

Consequences

  • Loose coupling and stable external addressing: neither side’s renames break the other.

  • Cost: most calls resolve an external id to its internal UUID first.

  • Watch the asymmetry: externalGameId and externalUserId are globally unique, but externalTaskId is unique only within its game.

See also