npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-ulid-jsi

v0.2.2

Published

High-performance ULID generator for React Native using JSI and C++. Supports both old and new architecture on iOS and Android.

Readme

react-native-ulid-jsi

npm version npm downloads license

⚡️ 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

🚀 Performance

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

Why so fast?

  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

Run your own benchmark

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

✨ Features

  • ⚡️ 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)

📦 Installation

npm install react-native-ulid-jsi

or with yarn:

yarn add react-native-ulid-jsi

iOS

cd ios && pod install

Android

No additional steps required. Gradle will handle everything automatically.

📖 Usage

Basic Usage

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)

With Seed Time

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

Validate ULID

import { isValid } from 'react-native-ulid-jsi';

const id = '01ARZ3NDEKTSV4RRFFQ69G5FAV';
const valid = isValid(id);
console.log(valid); // true

Decode Timestamp

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

🎯 API Reference

ulid(seedTime?: number): string

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:

const id1 = ulid(); // Uses current time
const id2 = ulid(1469918176385); // Uses custom time

isValid(id: string): boolean

Validates whether a string is a valid ULID.

Parameters:

  • id: String to validate

Returns: true if valid ULID, false otherwise.

Example:

isValid('01ARZ3NDEKTSV4RRFFQ69G5FAV'); // true
isValid('invalid-id'); // false

decodeTime(id: string): number

Extracts the timestamp from a ULID.

Parameters:

  • id: Valid ULID string

Returns: Timestamp in milliseconds since Unix epoch.

Example:

const timestamp = decodeTime('01ARZ3NDEKTSV4RRFFQ69G5FAV');
console.log(new Date(timestamp)); // Original creation time

🏗️ Architecture Support

This library is built to support both React Native architectures:

New Architecture (Fabric + TurboModules)

✅ Fully supported with JSI direct bindings ✅ Zero overhead JavaScript ↔️ Native communication ✅ Synchronous API access

Old Architecture (Bridge)

✅ Fully supported with JSI module installation ✅ Same performance benefits ✅ No breaking changes required

The library automatically detects and works with the architecture your app is using.

🔍 What is ULID?

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

ULID Format

 01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp       Randomness
  (48 bits)       (80 bits)

🔄 Monotonic Generation

This library implements monotonic ULID generation, ensuring that IDs are always increasing even when generated within the same millisecond.

How it works:

  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

Why monotonic?

// 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

💡 Use Cases

  • 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

🔧 Technical Details

  • 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)
    • Android: getrandom when available, falls back to /dev/urandom
    • Last resort: std::random_device (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+

📊 Comparison with JavaScript ULID

| 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 |

🤝 Contributing

Contributions are welcome! Please read our contributing guidelines and code of conduct.

Development Workflow

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

See CONTRIBUTING.md for detailed development setup.

📄 License

MIT © Alex Shumihin

🔗 Links

⭐️ Show Your Support

If this project helped you, please give it a ⭐️!


Made with ❤️ using create-react-native-library