ridgen
日本語 | English
A lightweight, high-performance Rust library for generating secure, URL-friendly unique string IDs.
Comparison with JavaScript Libraries
All tests performed with 1,000,000 iterations:
| Library | Language | Time (ms) | Throughput (million IDs/sec) | Notes |
|---|---|---|---|---|
| ridgen | Rust | ~340 | ~3.0 | This implementation ⚡ |
| uuid (v4) | JavaScript | 375 | ~2.7 | Standard UUID v4 |
| nanoid | JavaScript | 431 | ~2.3 | Widely used original |
| shortid | JavaScript | 3,220 | ~0.3 | Deprecated, slower |
| cuid2 | JavaScript | 34,274 | ~0.03 | Collision-resistant |
Key Takeaways
- ridgen achieves ~3.0 million IDs/sec throughput
- ~11% faster than uuid v4 while providing URL-friendly IDs
- ~30% faster than nanoid
- 9.5x faster than shortid
- 88x faster than cuid2
- Achieves maximum performance through batch random number generation
Note: The comparison is against JavaScript implementations running on Node.js. Rust implementations of UUID are not included in this benchmark.
Features
- 🚀 Fast: ~3.0 million IDs/sec
- 🔒 Secure: Uses cryptographically strong random number generation
- 📦 Lightweight: Minimal dependencies
- ✅ Simple API: Easy to use with error handling
- ⚡ Optimized: Batch random number generation for maximum performance
Installation
For Rust
Add this to your Cargo.toml:
[]
= "0.1.0"
For JavaScript/TypeScript (WASM)
Usage
Rust
use generate;
JavaScript/TypeScript
This package is built with WASM and supports modern environments.
import from "ridgen";
const id = ;
console.log;
Supported Environments
- Node.js: (ESM) v14.16.0 or later
- Bun: Native support
- Deno: Supported
- Modern bundlers: Vite, Webpack, Rollup
[!IMPORTANT]
- ESM Only: This package only supports ECMAScript Modules (ESM). CommonJS (
require) is not supported.- WASM Initialization: In environments that support top-level WASM (like Bun or Webpack), it works immediately. For other environments, ensure your bundler is configured to handle
.wasmfiles.
Benchmarks
Environment
- Date: 2026-01-20
- CPU: x86_64
- Rust: 1.92.0
- Build: release
- Node.js: v24.12.0
Rust (ridgen)
Performance test with 1,000,000 iterations generating 16-character IDs:
- Total time: ~340ms (average)
- Throughput: ~2.9-3.0 million IDs/sec
Note: Uses thread_rng (Default) for random number generation.
Why no SmallRng?: Although SmallRng is faster, it is not cryptographically secure. ridgen prioritizes security by using thread_rng to ensure IDs are unpredictable, while maintaining high performance through batch generation.
Optimization: Uses batch random number generation (RngCore::fill_bytes) instead of calling gen_range() for each character, reducing CPU instruction count and improving performance by ~20-25%.
Character Set
The library uses a URL-safe character set:
- Lowercase letters:
a-z - Uppercase letters:
A-Z - Numbers:
0-9
Total: 62 characters
Error Handling
The generate function returns a Result<String, RidgenError>:
Ok(String): Successfully generated IDErr(RidgenError::InvalidLength): If length is 0
Safety and unsafe Usage
This library uses a small amount of unsafe code for performance reasons.
Specifically, String::from_utf8_unchecked is used when constructing the final ID string.
Why is this safe?
- The character set consists only of ASCII characters (
a-zA-Z0-9) - Each byte pushed into the buffer is guaranteed to be valid UTF-8
- No user input or external data is involved
Because these invariants are strictly controlled, skipping UTF-8 validation is safe and avoids unnecessary runtime checks.
Trade-off
- ✅ Improved performance (avoids an extra UTF-8 validation pass)
- ⚠️ Requires careful maintenance if the character set changes
If the character set is ever modified to include non-ASCII characters, this unsafe usage must be revisited.
Distribution Characteristics
This implementation uses a simple modulo operation to map random bytes to the character set:
index = random_byte % 62
Modulo Bias
Since 256 is not evenly divisible by 62, this introduces a small distribution bias:
- The first 8 characters in the charset have a slightly higher probability
- The bias is approximately 1/256 per character
Why this is acceptable here
- The bias is extremely small and negligible for most ID generation use cases
- This approach avoids additional branching and rejection sampling, improving performance
- Many real-world ID systems accept this trade-off for speed
Security Note
This library prioritizes performance and simplicity over perfect uniform distribution. If strict cryptographic uniformity is required, consider using rejection sampling or other methods.
Running Benchmarks
Rust Benchmark
JavaScript Benchmark
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.