Give new orders uuid7 ids

Python · Python · intermediate · modification

Moves new orders from uuid1 to uuid7 ids now that we are on Python 3.14 and `uuid.uuid7()` is in the standard library. uuid1 puts the low bits of the timestamp first and can embed a MAC-derived node identifier in the ids we hand to customers; uuid7 starts with the creation time in milliseconds, so new ids sort by creation time (to the millisecond) and inserts land at the end of the primary key index instead of all over it. Old orders keep their uuid1 ids, and `id_timestamp` now accepts both versions, so `placed_at` and the sales report keep reading the order time from the id for old and new orders alike. Nothing in the database changes.

Order service on CPython 3.14 (`requires-python = ">=3.14"`; production image and CI moved to 3.14 last month). Order ids are stored in a PostgreSQL `uuid` primary key column. `new_order_id` is called once per order by `OrderService.create`, which runs in Gunicorn sync workers (one thread per process). `orders/ids.py` is the only place that generates order ids or reads a time out of them; `GET /orders/{id}` serialises `placed_at` with `isoformat()`, and the nightly sales report groups orders by the UTC date of `id_timestamp(order.id)`.

Requirements

Files touched

--- orders/ids.py
 from datetime import UTC, datetime, timedelta
 
-_UUID1_EPOCH = datetime(1582, 10, 15, tzinfo=UTC)
+# Orders created before this change carry uuid1 ids, newer ones uuid7.
+# Both are time-based, so the creation time can be read from the id.
+_TIME_BASED_VERSIONS = (1, 7)
+_GREGORIAN_EPOCH = datetime(1582, 10, 15, tzinfo=UTC)
 
 
 def new_order_id() -> uuid.UUID:
-    """A fresh id for a new order."""
-    return uuid.uuid1()
+    """A fresh id for a new order.
+
+    uuid7 starts with its creation time in milliseconds, so ids sort by
+    creation time (to the millisecond) and new rows go to the end of the
+    primary key index. Unlike uuid1, it has no MAC-derived node field.
+    """
+    return uuid.uuid7()
 
 
 def id_timestamp(order_id: uuid.UUID) -> datetime:
     """When the order id was generated, as an aware UTC datetime."""
-    if order_id.version != 1:
+    if order_id.version not in _TIME_BASED_VERSIONS:
         raise ValueError(f"not a time-based order id: {order_id}")
-    return _UUID1_EPOCH + timedelta(microseconds=order_id.time // 10)
+    return _GREGORIAN_EPOCH + timedelta(microseconds=order_id.time // 10)
 

Review this PR

Python practice