Skip to content

sovereignbase/sharding

npm version CI codecov license

sharding

Deterministic shard-index derivation for string and byte inputs. Use it when every caller must route the same payload into the same shard without shared state, caches, or runtime-local coordination.

Compatibility

  • Runtimes: Node >= 20; Browsers: modern browsers with crypto.subtle and TextEncoder; Workers/Edge: runtimes with crypto.subtle, TextEncoder, and BigInt.
  • Module format: ESM and CJS.
  • Required globals / APIs: crypto, crypto.subtle, TextEncoder, BigInt.
  • TypeScript: bundled types. ShardingErrorCode is exported as a type; the runtime error class is intentionally not public API.

Goals

  • Deterministic routing from the same input and shard count.
  • Byte-oriented behavior with support for strings and normalized ByteSource inputs.
  • Small public API surface: one runtime function, one exported error-code type.
  • No hidden state, caches, or environment-specific routing behavior.
  • Consistent results across Node, Bun, Deno, browsers, Cloudflare Workers, and edge runtimes.

Installation

npm install @sovereignbase/sharding
# or
pnpm add @sovereignbase/sharding
# or
yarn add @sovereignbase/sharding
# or
bun add @sovereignbase/sharding
# or
deno add jsr:@sovereignbase/sharding
# or
vlt install jsr:@sovereignbase/sharding

Usage

String input

import { shardIndexFor } from '@sovereignbase/sharding'

const shards = ['s0', 's1', 's2', 's3', 's4', 's5', 's6', 's7']

const index = await shardIndexFor('alpha', shards.length)
const shard = shards[index]

console.log(index) // 5
console.log(shard) // "s5"

Byte input

import { fromJSON } from '@sovereignbase/bytecodec'
import { shardIndexFor } from '@sovereignbase/sharding'

const payload = fromJSON({ ok: true })
const index = await shardIndexFor(payload, 8)

console.log(index) // 0

Validation errors

import { shardIndexFor, type ShardingErrorCode } from '@sovereignbase/sharding'

try {
  await shardIndexFor('alpha', 0)
} catch (error) {
  const code = (error as { code?: ShardingErrorCode }).code

  if (code === 'SHARD_COUNT_INVALID') {
    console.error('Shard count must be a positive integer.')
  }
}

Runtime behavior

Node

Uses the host WebCrypto implementation via globalThis.crypto.subtle.digest.

Browsers / Edge runtimes / Workers

Uses the same crypto.subtle.digest('SHA-512', ...) flow as Node, so routing remains deterministic across tested hosts.

Validation & errors

Invalid shardsLength values throw an error with:

  • name: ShardingError
  • code: SHARD_COUNT_INVALID
  • message: @sovereignbase/sharding shardsLength must be a positive integer

ShardingErrorCode is public as a type for tooling and IntelliSense. The ShardingError class itself is internal.

State & caching

The package is stateless. It does not cache inputs, hashes, or shard mappings.

Tests

Suite: unit + integration (Node), E2E across runtimes

Matrix:

  • Node ESM and CJS
  • Bun ESM and CJS
  • Deno ESM
  • Cloudflare Workers ESM via local Wrangler dev
  • Edge Runtime ESM
  • Playwright browsers: Chromium, Firefox, WebKit, Pixel 5 emulation, iPhone 12 emulation

Coverage: c8 — 100% statements / branches / functions / lines

Latest verified local run:

  • npm test
  • Node v22.14.0 (win32 x64)
  • Bun 1.3.10
  • Deno 2.7.7

Benchmarks

How it was run: node benchmark/bench.js

Environment: Node v22.14.0 (win32 x64)

Results:

Benchmark Result
string short 7,579 ops/s (0.132 ms/op, 2000 ops)
string long 6,229 ops/s (0.161 ms/op, 2000 ops)
bytes json 9,712 ops/s (0.103 ms/op, 2000 ops)
bytes raw 9,539 ops/s (0.105 ms/op, 2000 ops)

Results vary by machine.

License

Apache-2.0