ewan's projects — docs

projects

@ewanc26/tid

March 4, 2026

# atproto# typescript# library# malachite# tools

@ewanc26/tid is a tiny TypeScript library for generating, validating, decoding, and comparing AT Protocol TIDs (Timestamp Identifiers). It has no runtime dependencies, ships with type definitions, and works in Node.js 20+, Deno, Bun, and modern browsers via the Web Crypto API.

TIDs are 13-character, lexicographically sortable record keys used across the AT Protocol and Bluesky. They encode a microsecond-precision Unix timestamp and a 5-bit clock ID. Within a JS context, the library guarantees monotonicity — if records arrive out of order, the clock is bumped forward so every generated TID is strictly increasing.

Install

npm install @ewanc26/tid
# or
pnpm add @ewanc26/tid

Usage

Generate a TID

import { generateTID, generateNextTID } from '@ewanc26/tid';

// From a historical timestamp (ISO string or Date)
const tid = generateTID('2023-11-01T12:00:00Z');
const tid2 = generateTID(new Date('2024-03-15T09:30:00Z'));

// For the current wall-clock time
const currentTid = generateNextTID();

Validate

import { validateTid } from '@ewanc26/tid';

validateTid('3jzfcijpj2z2a'); // true
validateTid('not-a-tid');     // false

Decode

import { decodeTid } from '@ewanc26/tid';

const { timestampUs, clockId, date } = decodeTid('3jzfcijpj2z2a');
// timestampUs — microseconds since Unix epoch
// clockId     — 0–31
// date        — millisecond-precision Date object

Sort

import { compareTids } from '@ewanc26/tid';

const tids = ['3jzfcijpj2z2a', '3jzfabc000022', '3jzfzzzzzzz2a'];
tids.sort(compareTids);

CommonJS

const { generateTID, validateTid } = require('@ewanc26/tid');

API

Export Signature Description
generateTID (source: string | Date) => string Generate a TID for a historical timestamp
generateNextTID () => string Generate a TID for the current wall-clock time
validateTid (tid: string) => boolean Returns true if the string is a well-formed TID
decodeTid (tid: string) => DecodedTid Decode a TID into its timestamp, clockId, and Date
compareTids (a: string, b: string) => -1 | 0 | 1 Lexicographic comparator for sorting
resetTidClock () => void Reset the monotonic clock (tests only)

DecodedTid

interface DecodedTid {
  timestampUs: number; // microseconds since Unix epoch
  clockId: number;     // 0–31
  date: Date;          // millisecond-precision equivalent
}

Spec notes

  • TIDs use a custom AT Protocol base-32 alphabet: 234567abcdefghijklmnopqrstuvwxyz.
  • The first 11 characters encode a microsecond-precision Unix timestamp; the last 2 encode a 5-bit clock ID (0–31).
  • The clock ID is randomised once at module load (per JS context). When multiple TIDs would land on the same microsecond the implementation nudges the timestamp forward rather than the clock ID, preserving lexicographic monotonicity.
  • Full specification: atproto.com/specs/tid.

Behavioural notes

  • Monotonicity is per-JS-context only. Records generated in different processes or machines may collide within the same microsecond, which is why the 5-bit clock ID exists.
  • The package does not coordinate across processes. If you need globally unique sequencing beyond the spec, combine TIDs with a per-host identifier or use a server-side sequencer.

Licence

AGPL-3.0-only — same as Malachite.


← all docs