Developer tools · UUID generator
Sequential IDs Leak Business Data: Why Public APIs Expose UUIDs
· Why it matters
uuid cryptography browser-apis
Auto-increment IDs tell outsiders how many orders you take and make every record enumerable. This post explains what exposing UUIDs fixes, what it does not, and how to introduce them without a migration.
Your invoice numbers are telling competitors your volume — the information leak in /orders/10482
An API endpoint that returns /orders/10482 tells an outsider more than the order details themselves. The numeric identifier signals that you have processed at least ten thousand orders, implies information about your growth rate and makes every order guessable. A simple loop through sequential numbers retrieves all records without authentication or permission checks. This pattern appears everywhere—in URLs, database keys, invoice numbers and transaction IDs—even when the system requires authentication to view any single record. The problem compounds in reporting and analysis. An attacker who can fetch /orders/1, /orders/2, and continuing through /orders/10482 gains a comprehensive view of your order history and trends.
Enumeration and scraping — how sequential IDs turn one exposed record into all of them
The sequential pattern reveals trends in when orders arrive, which products are mentioned and patterns in pricing. An observer learns the rate at which your business is growing or contracting. That information, derived only from ID enumeration, can inform competitive strategy, guide social engineering or inform timing for other attacks. The exposure costs nothing to discover and appears in URLs, browser history, cached pages and server logs. This is not theoretical: competitive intelligence firms and curious engineers routinely extract business metrics from publicly enumerable IDs. A sample of order numbers reveals the production rate and total volume to anyone motivated enough to collect data and perform basic analysis.
The German tank problem in one paragraph — estimating totals from a sample of sequential numbers
Enumeration applies statistical analysis to estimate total volumes and track temporal patterns. If the first order occurred on a known date and you capture evidence of ten orders spread across a week, the mean interval estimates the overall rate. Competitors, investors and attackers can derive your velocity without accessing any customer data beyond the IDs themselves. Sequential identifiers guarantee that every ID greater than the current number predicts future orders; every ID lower than the minimum in a sample confirms your operation was smaller previously. Historical data points create a timeline of growth and enable forecasting. This same principle applies across industries: financial transactions, shipping orders, medical records and any system exposing sequential IDs.
What UUIDs fix — unguessable references and no growth signal in the ID itself
A randomly generated UUID contains 122 bits of entropy when generated from a cryptographically secure source as RFC 9562 specifies for version 4. The identifier is not guessable, not enumerable and reveals nothing about growth rate or volume to external observers. An attacker who knows /orders/9a1f4e2b-7c3e-4d1a-8a5f-1b2c3d4e5f60 cannot predict the next order's UUID or walk backward through your historical IDs with any reasonable confidence. The UUID itself becomes a reference that is unique but completely opaque. The random distribution means multiple queries reveal no pattern, no progression and no velocity information to external observers monitoring your API.
What UUIDs do not fix — an unguessable ID is not authorization, and obscurity still needs access checks behind it
Replacing sequential IDs with UUIDs in public APIs is operationally simple and requires no complex coordination between systems. Add a UUID column to your orders table, generate one for every new order, expose the UUID in responses and gradually deprecate the numeric key. Your internal systems can continue using integer primary keys for performance and simplicity; only the public interface changes. The old sequential ID remains in the database for your own reference or audit trails, but customers and third parties see only the UUID. This dual-key approach is a best practice for maintaining existing index performance while exposing opaque identifiers to the outside world.
Worked example — adding a public UUID column alongside an internal integer key and exposing only the former
This approach is distinct from actual authorization because a UUID is not a password and obscurity is not a security control. A customer who has legitimate access to /orders/{their-uuid} should be able to view it, but /orders/{someone-elses-uuid} must still be rejected by your access checks. The UUID hides the order number from casual inspection and prevents statistical analysis via enumeration, but your authentication and authorization logic remains the responsibility of your application code. The protection is layered: the UUID stops information leaks in the identifier itself, and access control enforces who may act on that identifier.
What this does not cover — the index-performance trade-offs of random keys, discussed in a separate post
The operational boundary matters because UUIDs fix the information leak in the ID itself but do not replace access control mechanisms. If a customer has an API key and sufficient permissions, they can still make requests to your system. The scope of what they can access is determined by your permission model and role definitions, not the ID format. The benefit of UUIDs is purely that the identifier stops broadcasting volume, sequence and growth data to anyone who can observe it. A well-designed system combines UUID opacity with explicit access control checks on every request to the API.
Takeaway: separate public references from internal keys — the ToolAcre generator supplies CSPRNG-backed UUIDs for the public side
A practical migration avoids a flag day by supporting both formats gradually. If you version your endpoints, the v1 API can continue returning integer IDs while v2 returns UUIDs. Clients transition at their own pace without requiring coordinated cutover. Your internal database queries remain unchanged: they still filter by the integer id because your indexes are built on that column and your foreign keys reference it. Only the data returned to clients changes. The ToolAcre UUID generator produces the version-4 format you will use; each output is a correct RFC 9562 UUID ready for storage, deployment and gradual migration scenarios.