Generate compact human-facing references from ULIDs, UUIDs, and other stable identifiers
Project description
CompactRef
Generate compact, human-facing references from ULIDs, UUIDs and other stable internal identifiers.
CompactRef is useful when an application keeps a full internal identifier but needs a shorter reference for users, support teams, documents or searches.
Installation
pip install compactref
Generate a reference from a ULID
from compactref import generate_reference
reference = generate_reference(
"01J2H8NQPG6B5X8KGN97SX3R5C",
)
print(reference)
Possible output:
20260710482731
Add a prefix and separators
from compactref import generate_reference
reference = generate_reference(
"01J2H8NQPG6B5X8KGN97SX3R5C",
prefix="INC",
separator="-",
)
print(reference)
Possible output:
INC-20260710-482731
Use a UUID
from uuid import uuid4
from compactref import generate_reference
internal_id = uuid4()
reference = generate_reference(internal_id)
Configure the suffix length
reference = generate_reference(
"01J2H8NQPG6B5X8KGN97SX3R5C",
suffix_length=8,
)
Possible output:
2026071048273164
Change the date format
The date_format argument accepts any datetime.strftime pattern. A
finer-grained format also produces smaller collision buckets (see
Choosing a suffix length).
reference = generate_reference(
"01J2H8NQPG6B5X8KGN97SX3R5C",
date_format="%Y%m%d-%H",
separator="-",
prefix="INC",
)
Possible output:
INC-20260710-14-482731
Use an integer or bytes identifier
from compactref import generate_reference
from_integer = generate_reference(123456789)
from_bytes = generate_reference(b"internal-record-123")
Deterministic generation
The same identifier, date and configuration produce the same reference:
from datetime import datetime
from compactref import generate_reference
generated_at = datetime(2026, 7, 10)
first = generate_reference(
"01J2H8NQPG6B5X8KGN97SX3R5C",
generated_at=generated_at,
)
second = generate_reference(
"01J2H8NQPG6B5X8KGN97SX3R5C",
generated_at=generated_at,
)
assert first == second
Supported source types
CompactRef accepts:
- ULIDs represented as strings
- UUID objects
- strings
- bytes
- non-negative integers
Choosing a suffix length
A reference is unique only within a single bucket — references that share the same prefix and date part. Because the date resets each day, what matters is how many references you expect per bucket (for the default format, per day), not the all-time total.
Two helpers size the suffix using the birthday model.
Estimate the collision risk
collision_probability(reference_count, suffix_length) returns the
probability that at least two references in one bucket share the same
suffix:
from compactref import collision_probability
collision_probability(50, suffix_length=4) # 0.1153 -> ~11.5%
collision_probability(50, suffix_length=6) # 0.0012 -> ~0.1%
collision_probability(120, suffix_length=4) # 0.5103 -> coin flip
Find a safe volume
max_references(suffix_length, max_probability=0.01) returns the
largest number of references that keeps the risk at or below the
threshold (1% by default):
from compactref import max_references
max_references(4) # 14 -> under 1% risk with 4 digits
max_references(6) # 142 -> under 1% risk with 6 digits
max_references(6, 0.05) # 320 -> if you accept up to 5% risk
Pick a length for your volume
from compactref import collision_probability
expected_per_day = 200
for length in range(4, 9):
risk = collision_probability(expected_per_day, suffix_length=length)
print(f"{length} digits -> {risk:.3%}")
# 4 digits -> 86.330%
# 5 digits -> 18.045%
# 6 digits -> 1.970%
# 7 digits -> 0.199%
# 8 digits -> 0.020%
For roughly 200 references per day, a 7-digit suffix keeps the risk well under 1%.
Uniqueness warning
CompactRef does not replace the original internal identifier.
Shortening an identifier reduces the number of possible values. Different internal identifiers can produce the same compact reference.
Applications requiring unique references should:
- Keep the original ULID or UUID as the internal identifier.
- Add a unique constraint to the reference column.
- Detect and handle the unlikely possibility of a collision.
- Increase
suffix_lengthwhen the expected volume requires it.
Requirements
Python 3.10 or newer.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file compactref-0.1.0.tar.gz.
File metadata
- Download URL: compactref-0.1.0.tar.gz
- Upload date:
- Size: 7.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b228211b31549abdd89f8a39bc471487ce5a206166e7bace5ebafb05ba7f6e0
|
|
| MD5 |
4fa049e3cd1833e2c0b3459db2fb0ae0
|
|
| BLAKE2b-256 |
24ff206cf6f0c48d8fc1dd5e4dc49ed421bf3c9d490db7f25798ef474f738517
|
File details
Details for the file compactref-0.1.0-py3-none-any.whl.
File metadata
- Download URL: compactref-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de364622959134d4cc28c503a1998f12816e6d59dfb03c370b3e49ff5c7d130f
|
|
| MD5 |
cc3a0be5c6f58e5589438c5e6591715b
|
|
| BLAKE2b-256 |
1c7176f310ac5f3aab50843b03af22a75e08b80427893f0328aab58e62c41311
|