
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@owpz/ksuid
Advanced tools
@owpz/ksuid is an efficient, comprehensive, production-ready TypeScript library for generating and parsing a specific kind of globally unique identifier called a KSUID. This library serves as a 'near' feature-complete port of the Go reference implementation with 100% compatibility. Given the same inputs, KSUID tokens generated by either library will deterministically be the same output.
npm install @owpz/ksuid
KSUID is for K-Sortable Unique IDentifier. It is a kind of globally unique identifier similar to a RFC 4122 UUID, built from the ground-up to be "naturally" sorted by generation timestamp without any special type-aware logic.
In short, running a set of KSUIDs through the UNIX sort command will result in a list ordered by
generation time.
There are numerous methods for generating unique identifiers, so why KSUID?
Even if only one of these properties are important to you, KSUID is a great choice! Many projects chose to use KSUIDs just because the text representation is copy-and-paste friendly.
For a follow up read on the topic: A brief history of UUID
Unlike the more ubiquitous UUIDv4, a KSUID contains a timestamp component that allows them to be loosely sorted by generation time. This is not a strong guarantee (an invariant) as it depends on wall clocks, but is still incredibly useful in practice. Both the binary and text representations will sort by creation time without any special sorting logic.
While RFC 4122 UUIDv1s do include a time component, there aren't enough bytes of randomness to provide strong protection against collisions (duplicates). With such a low amount of entropy, it is feasible for a malicious party to guess generated IDs, creating a problem for systems whose security is, implicitly or explicitly, sensitive to an adversary guessing identifiers.
To fit into a 64-bit number space, Snowflake IDs and its derivatives require coordination to avoid collisions, which significantly increases the deployment complexity and operational burden.
A KSUID includes 128 bits of pseudorandom data ("entropy"). This number space is 64 times larger than the 122 bits used by the well-accepted RFC 4122 UUIDv4 standard. The additional timestamp component can be considered "bonus entropy" which further decreases the probability of collisions, to the point of physical infeasibility in any practical implementation.
The text and binary representations are lexicographically sortable, which allows them to be dropped into systems which do not natively support KSUIDs and retain their time-ordered property.
The text representation is an alphanumeric base62 encoding, so it "fits" anywhere alphanumeric strings are accepted. No delimiters are used, so stringified KSUIDs won't be inadvertently truncated or tokenized when interpreted by software that is designed for human-readable text, a common problem for the text representation of RFC 4122 UUIDs.
Binary KSUIDs are 20-bytes: a 32-bit unsigned integer UTC timestamp and a 128-bit randomly generated payload. The timestamp uses big-endian encoding, to support lexicographic sorting. The timestamp epoch is adjusted to May 13th, 2014, providing over 100 years of life. The payload is generated by a cryptographically-strong pseudorandom number generator.
The text representation is always 27 characters, encoded in alphanumeric base62 that will lexicographically sort by timestamp.
This library is designed for performance-critical code paths with comprehensive benchmarking to validate production readiness:
# Run performance benchmarks
npm run benchmark
# Run stress tests
npm run stress-test
# Run both benchmark and stress tests
npm run perf
# Compare with Go implementation performance
npm run perf:compare
Our benchmarks show:
See PERFORMANCE_COMPARISON.md for detailed benchmarks and analysis.
The Sequence type is optimized for scenarios requiring high-volume KSUID generation, providing up
to 65,536 monotonic KSUIDs from a single seed with excellent performance characteristics.
This TypeScript implementation is built on the foundation of the battle-tested Go library that has been used in production at Segment for several years across diverse, high-scale distributed systems.
This TypeScript port maintains complete compatibility while adding modern JavaScript/TypeScript tooling and comprehensive performance validation.
✅ Complete KSUID Implementation
✅ Advanced Navigation
.next() and .prev() methods with overflow handling✅ Monotonic Sequence Generation
✅ Sorting & Comparison
✅ Multiple Constructors
fromParts() - Build from timestamp + payloadfromBytes() - Build from raw 20-byte bufferparseOrNil() - Safe parsing with nil fallback*OrNil variants for error-safe operations✅ Command Line Interface
npx ksuid -n 5npx ksuid -f inspect <ksuid>✅ TypeScript Support
This library focuses on core KSUID functionality and integrates seamlessly with the broader ecosystem:
Database drivers and ORM integrations are not included in this core library. Instead, they are available as separate, focused packages:
@owpz/prisma-ksuid - Prisma
custom scalar typeimport { KSUID } from "@owpz/ksuid";
// Generate a new KSUID
const id = KSUID.random();
console.log(id.toString()); // "0o5Fs0EELR0fUjHjbCnEtdUwx3e"
// Parse a KSUID string
const parsed = KSUID.parse("0o5Fs0EELR0fUjHjbCnEtdUwx3e");
console.log(parsed.timestamp); // 107608047
console.log(parsed.payload); // <Buffer 88 99 aa bb cc dd ee ff ...>
// Safe parsing
const safe = KSUID.parseOrNil("invalid"); // Returns KSUID.nil instead of throwing
// Navigate through KSUID space
const current = KSUID.random();
const next = current.next(); // Next KSUID in sequence
const prev = current.prev(); // Previous KSUID in sequence
console.log(prev.compare(current)); // -1 (prev < current)
console.log(current.compare(next)); // -1 (current < next)
import { Sequence } from "@owpz/ksuid";
// Generate ordered sequence of KSUIDs
const sequence = new Sequence({ seed: KSUID.random() });
const ids = [];
for (let i = 0; i < 100; i++) {
const id = sequence.next();
if (id) ids.push(id);
}
// All IDs share same timestamp but are lexicographically ordered
console.log(ids.every((id, i) => i === 0 || ids[i - 1].compare(id) < 0)); // true
import { sort, isSorted } from "@owpz/ksuid";
const ksuids = [KSUID.random(), KSUID.random(), KSUID.random()];
sort(ksuids); // Sort in place
console.log(isSorted(ksuids)); // true
There are times when you are sure your KSUID is correct but need to get it from bytes or string and
pass it to a structure. For this, there are OrNil functions that return KSUID.nil on error:
// Functions available:
// - parseOrNil()
// - fromPartsOrNil()
// - fromBytesOrNil()
// Example without OrNil (verbose)
function getPosts(beforeBytes: Buffer, afterBytes: Buffer) {
let before: KSUID, after: KSUID;
try {
before = KSUID.fromBytes(beforeBytes);
after = KSUID.fromBytes(afterBytes);
} catch (error) {
// handle error
return;
}
const sortOptions = { before, after };
}
// Much more convenient with OrNil
function getPosts(beforeBytes: Buffer, afterBytes: Buffer) {
const sortOptions = {
before: KSUID.fromBytesOrNil(beforeBytes),
after: KSUID.fromBytesOrNil(afterBytes),
};
}
This package comes with a command-line tool ksuid, useful for generating KSUIDs as well as
inspecting the internal components of existing KSUIDs. Machine-friendly output is provided for
scripting use cases.
# Install globally (optional)
npm install -g @owpz/ksuid
# Or use with npx (recommended)
npx ksuid
$ npx ksuid
0ujsswThIGTUYm2K8FjOOfXtY1K
$ npx ksuid -n 4
0ujsszwN8NRY24YaXiTIE2VWDTS
0ujsswThIGTUYm2K8FjOOfXtY1K
0ujssxh0cECutqzMgbtXSGnjorm
0ujsszgFvbiEr7CDgE3z8MAUPFt
$ npx ksuid -f inspect 0ujtsYcgvSTl8PAuAdqWYSMnLOv
REPRESENTATION:
String: 0ujtsYcgvSTl8PAuAdqWYSMnLOv
Raw: 0669F7EFB5A1CD34B5F99D1154FB6853345C9735
COMPONENTS:
Time: 2017-10-09T21:00:47-07:00
Timestamp: 107608047
Payload: B5A1CD34B5F99D1154FB6853345C9735
$ npx ksuid -f inspect
REPRESENTATION:
String: 0ujzPyRiIAffKhBux4PvQdDqMHY
Raw: 066A029C73FC1AA3B2446246D6E89FCD909E8FE8
COMPONENTS:
Time: 2017-10-09T21:46:20-07:00
Timestamp: 107610780
Payload: 73FC1AA3B2446246D6E89FCD909E8FE8
$ npx ksuid -f template -t '{{ .Time }}: {{ .Payload }}' 0ujtsYcgvSTl8PAuAdqWYSMnLOv
2017-10-09T21:00:47-07:00: B5A1CD34B5F99D1154FB6853345C9735
$ npx ksuid -f template -t '{{ .Time }}: {{ .Payload }}' $(npx ksuid -n 4)
2017-10-09T21:05:37-07:00: 304102BC687E087CC3A811F21D113CCF
2017-10-09T21:05:37-07:00: EAF0B240A9BFA55E079D887120D962F0
2017-10-09T21:05:37-07:00: DF0761769909ABB0C7BB9D66F79FC041
2017-10-09T21:05:37-07:00: 1A8F0E3D0BDEB84A5FAD702876F46543
$ npx ksuid -f template -t '{ "timestamp": "{{ .Timestamp }}", "payload": "{{ .Payload }}", "ksuid": "{{.String}}"}' -n 4
{ "timestamp": "107611700", "payload": "9850EEEC191BF4FF26F99315CE43B0C8", "ksuid": "0uk1Hbc9dQ9pxyTqJ93IUrfhdGq"}
{ "timestamp": "107611700", "payload": "CC55072555316F45B8CA2D2979D3ED0A", "ksuid": "0uk1HdCJ6hUZKDgcxhpJwUl5ZEI"}
{ "timestamp": "107611700", "payload": "BA1C205D6177F0992D15EE606AE32238", "ksuid": "0uk1HcdvF0p8C20KtTfdRSB9XIm"}
{ "timestamp": "107611700", "payload": "67517BA309EA62AE7991B27BB6F2FCAC", "ksuid": "0uk1Ha7hGJ1Q9Xbnkt0yZgNwg3g"}
KSUID.random() - Generate random KSUIDKSUID.parse(string) - Parse KSUID string (throws on error)KSUID.parseOrNil(string) - Parse KSUID string (returns nil on error)KSUID.fromParts(timestamp, payload) - Build from componentsKSUID.fromPartsOrNil(timestamp, payload) - Build from components (nil on error)KSUID.fromBytes(buffer) - Build from 20-byte bufferKSUID.fromBytesOrNil(buffer) - Build from buffer (nil on error)KSUID.nil - The nil KSUID (all zeros).toString() - Get Base62 string representation.toBuffer() - Get raw 20-byte buffer.next() - Get next KSUID in sequence.prev() - Get previous KSUID in sequence.compare(other) - Compare with another KSUID (-1, 0, 1).isNil() - Check if this is the nil KSUID.timestamp - Unix timestamp (seconds since KSUID epoch).payload - 16-byte random payload as Buffernew Sequence({ seed }) - Create sequence generator.next() - Generate next KSUID in sequence (returns null when exhausted).bounds() - Get min/max bounds of sequence.reset() - Reset sequence to beginning.getCount() - Get current count of generated KSUIDs.isExhausted() - Check if sequence is exhaustedsort(ksuids) - Sort array of KSUIDs in placeisSorted(ksuids) - Check if array is sortedcompare(a, b) - Compare two KSUIDsKSUIDs work excellently as database identifiers. This core library provides the KSUID functionality, while database-specific integrations are available as separate packages.
// Store as string in any database
const user = {
id: KSUID.random().toString(), // "0o5sKzFDBc56T8mbUP8wH1KpSX7"
email: "user@example.com",
createdAt: new Date(),
};
// Query by KSUID string
const foundUser = await db.users.findOne({ id: "0o5sKzFDBc56T8mbUP8wH1KpSX7" });
npm install @owpz/prisma-ksuid
// Use the dedicated Prisma integration
import { KSUID } from "@owpz/ksuid";
// Custom scalar and generators available in @owpz/prisma-ksuid
// Store as string column
@Entity()
class User {
@PrimaryColumn("varchar", { length: 27 })
id: string = KSUID.random().toString();
@Column()
email: string;
}
-- PostgreSQL/MySQL/SQLite
CREATE TABLE users (
id VARCHAR(27) PRIMARY KEY, -- Exact KSUID length
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- KSUIDs naturally sort by creation time
SELECT * FROM users ORDER BY id; -- Chronological order!
This TypeScript implementation maintain 'near' 100% compatibility with the Go segmentio/ksuid library.
All compatibility test vectors were generated using the Go reference implementation at commit
d33724947fcfba7949906c2b1821e96a1c8d06e7 from the
segmentio/ksuid repository to ensure exact byte-for-byte
compatibility.
Verified Compatible Features:
Note on Time Format Differences: The CLI tools produce identical core data but format timestamps differently due to language-specific date formatting conventions:
2017-10-09 21:00:47 +0000 UTC (Go's default time.Format layout)2017-10-09T21:00:47.000Z (JavaScript's ISO 8601 standard)Both represent the exact same moment in time - only the string formatting differs between the two language ecosystems.
The following test vectors demonstrate perfect compatibility:
// Test Vector 1: Standard KSUID
const timestamp = 95004740;
const payload = Buffer.from("669f7efd7b6fe812278486085878563d", "hex");
const ksuid = KSUID.fromParts(timestamp, payload);
console.log(ksuid.toString()); // '0o5sKzFDBc56T8mbUP8wH1KpSX7'
console.log(ksuid.toBuffer().toString("hex"));
// '05a9a844669f7efd7b6fe812278486085878563d'
// ✅ Exact same results in Go:
// ksuid.FromParts(time.Unix(1495004740, 0), payload)
// String(): "0o5sKzFDBc56T8mbUP8wH1KpSX7"
// Bytes(): [5 169 168 68 102 159 126 253 ...]
# Cross-CLI Compatibility Test
# Generate with Go, inspect with TypeScript:
$ ./ksuid-go -f inspect 0o5sKzFDBc56T8mbUP8wH1KpSX7
String: 0o5sKzFDBc56T8mbUP8wH1KpSX7
Raw: 05A9A844669F7EFD7B6FE812278486085878563D
$ npx ksuid -f inspect 0o5sKzFDBc56T8mbUP8wH1KpSX7
String: 0o5sKzFDBc56T8mbUP8wH1KpSX7
Raw: 05A9A844669F7EFD7B6FE812278486085878563D
# ✅ Identical output
Our comprehensive test suite validates compatibility across multiple scenarios:
| Test Category | Test Cases | Pass Rate |
|---|---|---|
| String Encoding | 25 test vectors | ✅ 100% |
| Binary Format | 15 edge cases | ✅ 100% |
| Next/Prev Ops | 12 scenarios | ✅ 100% |
| Component Extract | 20 cases | ✅ 100% |
| Edge Cases | 18 boundary tests | ✅ 100% |
| CLI Compatibility | 10 format tests | ✅ 100% |
| Round-trip Tests | 50 random KSUIDs | ✅ 100% |
Overall Compatibility: 100% (89/89 tests passing)
# Run the full compatibility test suite
npm test
# Run only unit tests
npm test -- test/unit
# Run only integration tests (including Go compatibility)
npm test -- test/integration
# Run only Go compatibility tests
npm test -- test/integration/go-compatibility.test.ts
# Run only Go interoperability tests
npm test -- test/integration/go-interop.test.ts
For users who want to validate compatibility themselves, we provide Go validation tools in
docs/validation/:
# Generate fresh test vectors from Go implementation
cd docs/validation
go run generate-interop-vectors.go
# Run manual cross-validation tests
go run manual-test.go [optional-ksuid]
# Automated cross-validation script
./cross-validate.sh
See docs/validation/README.md for detailed validation instructions.
// Edge Case Test Vectors (validated against Go)
const testVectors = [
{
description: "Nil KSUID (all zeros)",
input: "000000000000000000000000000",
timestamp: 0,
payload: "00000000000000000000000000000000",
},
{
description: "Max KSUID value",
input: "aWgEPTl1tmebfsQzFP4bxwgy80V",
timestamp: 4294967295,
payload: "ffffffffffffffffffffffffffffffff",
},
{
description: "Epoch timestamp",
input: "000000296tiiBb3U904RIpygpjj",
timestamp: 0,
payload: "0123456789abcdef0123456789abcdef",
},
];
// All vectors verified to parse identically in both implementations
// Navigation operations produce identical results
const base = KSUID.parse("0o5sKzFDBc56T8mbUP8wH1KpSX7");
console.log(base.next().toString()); // '0o5sKzFDBc56T8mbUP8wH1KpSX8'
console.log(base.prev().toString()); // '0o5sKzFDBc56T8mbUP8wH1KpSX6'
// ✅ Go ksuid.Next()/Prev() produce identical strings
This implementation has been thoroughly tested for production use:
Existing Go applications can migrate seamlessly:
// Go code
ksuid := ksuid.New()
fmt.Println(ksuid.String())
next := ksuid.Next()
// TypeScript equivalent (identical output)
const ksuid = KSUID.random();
console.log(ksuid.toString());
const next = ksuid.next();
npm test # Run test suite (89/89 tests passing)
npm run build # Build TypeScript to JavaScript
npm run cli # Run CLI tool directly
We welcome contributions! Please see CONTRIBUTING.md for details on:
MIT License - see LICENSE file for details.
Based on the excellent Go implementation by Segment: https://github.com/segmentio/ksuid
This TypeScript port maintains full compatibility while adding JavaScript/TypeScript features and tooling.
FAQs
TypeScript implementation of KSUID with full feature parity to the Go version
We found that @owpz/ksuid demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.