This article discusses a critical API design best practice: avoiding the direct exposure of internal database primary keys (IDs) to clients. It advocates for using separate, public-facing identifiers to enhance security, improve system flexibility, and prevent data leakage, which are important considerations in system architecture.
Read original on Medium #system-designExposing internal database IDs directly in APIs can lead to several security and architectural vulnerabilities. These IDs often reveal implementation details, such as the total number of records, and can be used to infer system growth or enumerate resources. This can make systems more susceptible to scraping, data exploration, and potentially even denial-of-service attacks if IDs are guessable (e.g., sequential integers). From a system design perspective, tying the public API directly to internal database schema creates tight coupling, making future schema changes more difficult without breaking client applications.
To mitigate these risks, the recommended approach is to use public identifiers (Public IDs) that are distinct from internal database primary keys. These Public IDs should be opaque, non-sequential, and difficult to guess. UUIDs (Universally Unique Identifiers) are a common and effective choice for Public IDs, offering global uniqueness and randomness. Implementing Public IDs creates a crucial abstraction layer between the external API contract and the internal data storage mechanism.
Implementation Considerations
When implementing Public IDs, ensure they are indexed in the database for efficient lookups. Consider the trade-off between UUID v1 (time-based, potentially guessable parts) and UUID v4 (random) or ULIDs (Universally Unique Lexicographically Sortable Identifiers) which offer uniqueness and time-sortability, beneficial for indexing.