docs/ADAPTIVE_IDS.md
Feature: bd-ea2a13
Status: Implemented (v0.21+)
Beads uses adaptive hash ID lengths that automatically scale based on database size, optimizing for readability in small databases while preventing collisions as databases grow.
bd-a3f2 (4 chars)bd-7f3a8 (5 chars)bd-7f3a86 (6 chars)Users who actively archive old issues can keep their IDs shorter over time.
The collision probability is calculated using:
P(collision) ≈ 1 - e^(-n²/2N)
Where:
n = number of issues in databaseN = total possible IDs (36^length for lowercase alphanumeric)| Database Size | ID Length | Collision Probability |
|---|---|---|
| 0-500 | 4 chars | ~7% at 500 |
| 501-1500 | 5 chars | ~2% at 1500 |
| 1501+ | 6 chars | continues scaling |
If a collision occurs (rare), the algorithm automatically tries:
With 10 nonces per length, giving 30 attempts total.
Adaptive ID length is automatically enabled when using id_mode=hash. You can customize the behavior:
Default: 25% (0.25)
# More lenient (allow up to 50% collision probability)
bd config set max_collision_prob "0.50"
# Stricter (only allow 1% collision probability)
bd config set max_collision_prob "0.01"
Default: 4 chars
# Start with 5-char IDs minimum
bd config set min_hash_length "5"
# Very short IDs (use with caution)
bd config set min_hash_length "3"
Default: 8 chars
# Allow even longer IDs for huge databases
bd config set max_hash_length "10"
# Initialize with hash IDs
bd init --id-mode hash --prefix myproject
# First 500 issues get 4-char IDs
bd create "Fix bug" -p 1
# → myproject-a3f2
# After 1000 issues, switches to 5-char IDs
bd create "Add feature" -p 1
# → myproject-7f3a8c
# At 10,000 issues, uses 6-char IDs
bd create "Refactor" -p 1
# → myproject-b9d1e4
# Very strict collision tolerance
bd config set max_collision_prob "0.01"
# With 1% threshold and 100 issues, uses 4-char IDs
# (collision probability is ~0.3% with 4 chars)
# Force minimum 5-char IDs for consistency
bd config set min_hash_length "5"
# All IDs will be at least 5 chars now
bd create "Task" -p 1
# → myproject-7f3a8
Use scripts/collision-calculator.go to explore collision probabilities:
go run scripts/collision-calculator.go
Output shows:
internal/storage/dolt/adaptive_length.gointernal/storage/dolt/dolt.go (generateHashID)internal/storage/dolt/adaptive_length_test.gointernal/storage/dolt/adaptive_e2e_test.goConfiguration is stored in the config table:
INSERT INTO config (key, value) VALUES ('max_collision_prob', '0.25');
INSERT INTO config (key, value) VALUES ('min_hash_length', '4');
INSERT INTO config (key, value) VALUES ('max_hash_length', '8');
Existing databases with 6-char IDs will:
When migrating from sequential IDs to hash IDs with bd migrate --to-hash-ids:
min_hash_length if you want all IDs to be same lengthPotential improvements (not yet implemented):
Adaptive hash IDs are the default, but beads also supports sequential integer IDs
(bd-1, bd-2, ...) for projects that prefer human-readable numbering.
Counter mode is controlled by the issue_id_mode config key:
# Switch to sequential IDs
bd config set issue_id_mode counter
# Revert to hash IDs (default)
bd config set issue_id_mode hash
Tradeoff:
See CONFIG.md for full documentation on issue_id_mode=counter, including migration
guidance and per-prefix counter isolation.