idgen
The idgen package generates cryptographically secure, time-ordered, prefixed IDs built on UUIDv7. IDs are monotonically increasing within the same millisecond, making them safe to use as primary keys in sorted databases without hot-spotting.
Import path: ecom-engine/pkg/idgen
ID format
<prefix><uuidv7>
Examples:
usr_019123ab-cdef-7000-8000-000000000001
ord_019123ab-cdef-7000-8000-000000000002
evt_019123ab-cdef-7000-8000-000000000003
The prefix is a short lowercase string followed by an underscore (_). It makes IDs self-describing - you can identify the entity type at a glance without querying the database.
Functions
Generate
func Generate(prefix string) (string, error)
Creates a new UUIDv7 and prepends prefix. Returns an error if the OS CSPRNG is unavailable (should be extremely rare).
id, err := idgen.Generate("usr_")
// id → "usr_019123ab-cdef-7000-8000-000000000001"
MustGenerate
func MustGenerate(prefix string) string
Like Generate but panics on error. Use in initialization code or tests where error handling would be noise.
id := idgen.MustGenerate("evt_")
ToUUID
func ToUUID(prefixedID string) (uuid.UUID, error)
Strips the prefix and parses the remaining string as a uuid.UUID. Returns uuid.Nil and an error if the UUID portion is malformed. If no underscore is found, it attempts to parse the full string as a UUID directly.
Intended for the repository layer when storing IDs in columns that use UUID or BINARY(16) types.
rawUUID, err := idgen.ToUUID("ord_019123ab-cdef-7000-8000-000000000001")
// rawUUID → uuid.UUID{...}
MustToUUID
func MustToUUID(prefixedID string) uuid.UUID
Like ToUUID but panics on error.
rawUUID := idgen.MustToUUID("ord_019123ab-cdef-7000-8000-000000000001")
FromUUID
func FromUUID(prefix string, id uuid.UUID) string
Re-attaches the prefix to a raw uuid.UUID. The inverse of ToUUID. Use when reading UUID primary keys from the DB and reconstructing the prefixed application ID.
prefixedID := idgen.FromUUID("ord_", rawUUID)
// prefixedID → "ord_019123ab-cdef-7000-8000-000000000001"
Prefix conventions
| Entity | Prefix |
|---|---|
| User | usr_ |
| Order | ord_ |
| Product | prd_ |
| Cart | crt_ |
| Event | evt_ |
| Session | ses_ |
Define your module's prefix as a constant to avoid typos:
const orderPrefix = "ord_"
id, err := idgen.Generate(orderPrefix)
Why UUIDv7?
- Time-ordered - the first 48 bits encode the Unix millisecond timestamp, so rows inserted sequentially have monotonically increasing keys. This avoids B-tree page splits and hot-spotting in PostgreSQL.
- Random suffix - the remaining bits are random, preventing enumeration attacks.
- Standard format - compatible with any system that accepts UUID strings (Postgres
uuid, MySQLchar(36), etc.).