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:
externalGameIdandexternalUserIdare globally unique, butexternalTaskIdis unique only within its game.
See also¶
Domain Model - “Identifiers: internal vs. external” is the authoritative prose home.
Integrating with GAME - shows the resolve-once-then-use-external pattern.