High-performance ULID generator for React Native using JSI and C++. Supports both old and new architecture on iOS and Android.
npm install react-native-ulid-jsi


ā”ļø Ultra-fast ULID (Universally Unique Lexicographically Sortable Identifier) generator for React Native
Built with JSI (JavaScript Interface) and C++ for maximum performance. Features monotonic generation with thread-local state for guaranteed ID ordering. Supports both New Architecture (Fabric + TurboModules) and Old Architecture on iOS and Android.
š 500x faster than JavaScript | š Monotonic | š¦ Zero dependencies
500x faster than pure JavaScript implementations!
Comparison performed against the official ulid/javascript package.
| Implementation | Time (1000 iterations) | Performance |
|---------------|----------------------|-------------|
| react-native-ulid-jsi (JSI/C++) | 0.17ms | ā”ļø 500x faster |
| Pure JavaScript (ulid package) | 83.62ms | š Baseline |
```
react-native-ulid-jsi ā 0.17ms
JavaScript ULID āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā 83.62ms
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
500x performance gain
Benchmark performed on iPhone 16 Pro with production build
1. Zero Bridge Overhead: Direct JSI binding to C++ (no serialization)
2. Native Random Generation: Platform-specific secure random APIs
3. Optimized Encoding: Hand-tuned Base32 encoding in C++
4. Thread-local State: No synchronization overhead for monotonic generation
5. Minimal Allocations: Stack-allocated buffers, no heap fragmentation
`typescript
import { ulid } from 'react-native-ulid-jsi';
const iterations = 1000;
const start = performance.now();
for (let i = 0; i < iterations; i++) {
ulid();
}
const end = performance.now();
console.log(Generated ${iterations} ULIDs in ${(end - start).toFixed(2)}ms);`
// Output: Generated 1000 ULIDs in 0.17ms
- ā”ļø Lightning Fast - JSI + C++ implementation for native performance
- šļø New Architecture Ready - Full support for React Native's new architecture (Fabric + TurboModules)
- š Backward Compatible - Works seamlessly with old architecture
- š± Cross Platform - iOS and Android support
- šÆ Type Safe - Full TypeScript support
- šŖ¶ Lightweight - Zero dependencies, pure C++ implementation
- š Monotonic Generation - Guarantees increasing IDs even within the same millisecond
- ā±ļø Timestamp Encoded - Contains creation timestamp (first 48 bits)
- š² Cryptographically Secure - Platform-native secure random generation
- iOS: SecRandomCopyBytes (Security Framework)
- Android: getrandom when available, falls back to /dev/urandom
- š¤ Crockford's Base32 - Excludes ambiguous characters (I, L, O, U)
`sh`
npm install react-native-ulid-jsi
or with yarn:
`sh`
yarn add react-native-ulid-jsi
`sh`
cd ios && pod install
No additional steps required. Gradle will handle everything automatically.
`typescript
import { ulid } from 'react-native-ulid-jsi';
// Generate a new ULID
const id = ulid();
console.log(id); // 01ARZ3NDEKTSV4RRFFQ69G5FAV
// Generate multiple ULIDs - they will be monotonically increasing
const id1 = ulid(); // 01HGW4Z6C8ABCDEFGHIJKLMNOP
const id2 = ulid(); // 01HGW4Z6C8ABCDEFGHIJKLMNPQ (guaranteed > id1)
const id3 = ulid(); // 01HGW4Z6C8ABCDEFGHIJKLMNPR (guaranteed > id2)
`
`typescript
import { ulid } from 'react-native-ulid-jsi';
// Generate ULID with custom timestamp (milliseconds since epoch)
const timestamp = Date.now();
const id = ulid(timestamp);
console.log(id); // 01ARZ3NDEKTSV4RRFFQ69G5FAV
`
`typescript
import { isValid } from 'react-native-ulid-jsi';
const id = '01ARZ3NDEKTSV4RRFFQ69G5FAV';
const valid = isValid(id);
console.log(valid); // true
`
`typescript
import { decodeTime } from 'react-native-ulid-jsi';
const id = '01ARZ3NDEKTSV4RRFFQ69G5FAV';
const timestamp = decodeTime(id);
console.log(timestamp); // 1469918176385
console.log(new Date(timestamp)); // 2016-07-31T04:42:56.385Z
`
Generates a new ULID.
Parameters:
- seedTime (optional): Custom timestamp in milliseconds since Unix epoch. If not provided, uses current time.
Returns: A 26-character ULID string.
Example:
`typescript`
const id1 = ulid(); // Uses current time
const id2 = ulid(1469918176385); // Uses custom time
Validates whether a string is a valid ULID.
Parameters:
- id: String to validate
Returns: true if valid ULID, false otherwise.
Example:
`typescript`
isValid('01ARZ3NDEKTSV4RRFFQ69G5FAV'); // true
isValid('invalid-id'); // false
Extracts the timestamp from a ULID.
Parameters:
- id: Valid ULID string
Returns: Timestamp in milliseconds since Unix epoch.
Example:
`typescript`
const timestamp = decodeTime('01ARZ3NDEKTSV4RRFFQ69G5FAV');
console.log(new Date(timestamp)); // Original creation time
This library is built to support both React Native architectures:
The library automatically detects and works with the architecture your app is using.
ULID (Universally Unique Lexicographically Sortable Identifier) is a better alternative to UUID for many use cases:
- Sortable: Unlike UUIDs, ULIDs are lexicographically sortable
- Timestamp: Contains a timestamp component (first 48 bits)
- Compact: 26 characters vs UUID's 36 characters
- URL-safe: Uses Crockford's base32 encoding
- Case-insensitive: Easy to use in various contexts
- No special characters: Just alphanumeric characters
``
01AN4Z07BY 79KA1307SR9X4MV3
|----------| |----------------|
Timestamp Randomness
(48 bits) (80 bits)
This library implements monotonic ULID generation, ensuring that IDs are always increasing even when generated within the same millisecond.
1. Same timestamp: If multiple ULIDs are generated in the same millisecond, the random component is incremented instead of generating new random bytes
2. Overflow protection: If the random component overflows, a new random value is generated
3. Time progression: When time advances, a fresh random value is used
`typescript
// Without monotonic (pure random):
const id1 = ulid(); // 01HGW4Z6C8ABCDEFGHIJKLMNOP
const id2 = ulid(); // 01HGW4Z6C8ZYXWVUTSRQPONMLK ā Not guaranteed to be > id1
// With monotonic (this library):
const id1 = ulid(); // 01HGW4Z6C8ABCDEFGHIJKLMNOP
const id2 = ulid(); // 01HGW4Z6C8ABCDEFGHIJKLMNPQ ā
Always > id1
`
Benefits:
- ā
Database indexes work optimally (B-tree friendly)
- ā
No collisions within same millisecond
- ā
Guaranteed sortability
- ā
Better for distributed systems
- Database IDs: Sortable by creation time without separate timestamp field
- Distributed Systems: Generate unique IDs without coordination
- API Resources: URL-safe identifiers for REST APIs
- Event Sourcing: Time-ordered events with unique identifiers
- Logging: Sortable log entry identifiers
- File Names: Unique, sortable file names
- Implementation: Pure C++ with JSI (JavaScript Interface) bindings
- Monotonic Generation: Thread-local state ensures IDs increment even within same millisecond
- Thread Safety: Thread-local storage per thread, no locks or mutexes needed
- Random Generation (with automatic fallback):
- iOS: SecRandomCopyBytes (Security Framework)std::random_device
- Android: getrandom when available, falls back to /dev/urandom
- Last resort: (other platforms)
- Encoding: Crockford's Base32 (0-9, A-Z excluding I, L, O, U)
- Memory: Minimal allocation, optimized for mobile devices
- Dependencies: Zero - pure C++ standard library
- Bundle Size: Native module only, zero JavaScript bundle impact
- Platforms: iOS 12+, Android API 21+
| Feature | react-native-ulid-jsi | JavaScript ULID |
|---------|------------------|-----------------|
| Performance | ā”ļø 0.17ms (1000 ops) | š 83.62ms (1000 ops) |
| Speed Improvement | 500x faster | Baseline |
| Implementation | C++ / JSI | JavaScript |
| Monotonic | ā
Thread-local | ā ļø Varies by package |
| Architecture Support | New + Old | N/A |
| Secure Random | ā
Platform native | ā ļø JS Math.random or crypto |
| Bundle Impact | Native only (0 KB JS) | +5-10 KB bundle |
| Dependencies | Zero | Varies |
Contributions are welcome! Please read our contributing guidelines and code of conduct.
1. Fork the repository
2. Create your feature branch (git checkout -b feature/amazing-feature)git commit -m 'feat: add amazing feature'
3. Commit your changes ()git push origin feature/amazing-feature`)
4. Push to the branch (
5. Open a Pull Request
See CONTRIBUTING.md for detailed development setup.
MIT Ā© Alex Shumihin
- GitHub Repository
- npm Package
- Issues
- ULID Specification
If this project helped you, please give it a āļø!
---
Made with ā¤ļø using create-react-native-library