> **clickhouse-js-node-rowbinary** — chapter 6 of 11 in [ClickHouse/agent-skills](https://skillsdocs.com/ClickHouse/agent-skills).
>
> Book (all chapters, one file): https://skillsdocs.com/ClickHouse/agent-skills.md
> Machine manifest: https://skillsdocs.com/ClickHouse/agent-skills/.well-known/agent-skills/index.json
> Install the book: `npx skills add ClickHouse/agent-skills`
> Upstream: https://github.com/ClickHouse/agent-skills/blob/main/skills/clickhouse-js-node-rowbinary/SKILL.md @ `main`
> Raw bytes, no header: https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/SKILL.md
> Base for relative paths: https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/
> Licence: Apache-2.0 — https://spdx.org/licenses/Apache-2.0.html
>
> Bundled files (192), referenced from this skill's directory:
>   - `.gitignore` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/.gitignore
>   - `AGENTS.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/AGENTS.md
>   - `case-studies/iot-rowbinary-vs-json.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/case-studies/iot-rowbinary-vs-json.md
>   - `case-studies/ledger-rowbinary-vs-json.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/case-studies/ledger-rowbinary-vs-json.md
>   - `case-studies/logs-json-wins.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/case-studies/logs-json-wins.md
>   - `case-studies/wasm-vs-js.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/case-studies/wasm-vs-js.md
>   - `CHANGELOG.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/CHANGELOG.md
>   - `eval_result_composer.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/eval_result_composer.md
>   - `eval_result_haiku.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/eval_result_haiku.md
>   - `eval_result_sonnet.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/eval_result_sonnet.md
>   - `eval_result.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/eval_result.md
>   - `EXAMPLES.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/EXAMPLES.md
>   - `package-lock.json` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/package-lock.json
>   - `package.json` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/package.json
>   - `reader.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/reader.md
>   - `README.md` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/README.md
>   - `src/examples/carts.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/carts.ts
>   - `src/examples/events.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/events.ts
>   - `src/examples/iot.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/iot.ts
>   - `src/examples/ledger.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/ledger.ts
>   - `src/examples/logs.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/logs.ts
>   - `src/examples/observability.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/observability.ts
>   - `src/examples/orders.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/orders.ts
>   - `src/examples/profiles.ts` — https://raw.githubusercontent.com/ClickHouse/agent-skills/main/skills/clickhouse-js-node-rowbinary/src/examples/profiles.ts
>   - …and 168 more, listed in https://skillsdocs.com/api/v1/books/ClickHouse/agent-skills/skills/clickhouse-js-node-rowbinary
>
> Content © its authors, served unmodified. Takedown: https://github.com/kyleledbetter/skillsdocs/issues/new?labels=takedown&title=Takedown+request

<!-- Verbatim upstream SKILL.md follows, YAML frontmatter included. -->

---
name: clickhouse-js-node-rowbinary
description: >
  Generate TypeScript/JavaScript code that reads/decodes AND writes/encodes
  ClickHouse RowBinary streams for the ClickHouse HTTP server.
  Use this skill whenever a user wants to parse or produce `RowBinary`,
  `RowBinaryWithNames`, or `RowBinaryWithNamesAndTypes`.
  Node.js only, doesn't cover browsers.
---

# ClickHouse JS RowBinary Codec Generator for Node.js

This skill generates both directions of the wire format: **readers** (decode
bytes → values) and **writers** (encode values → bytes, the mirror). A given
task normally needs only one side. This file is the shared entry point — the
format gate plus the principles common to both directions; the per-direction
decisions, guidance, and the per-type reference tables live in two sibling files.

**Pick your side — read only the one you need:**

- **Decoding a `RowBinary*` response** from ClickHouse into JS values →
  **[reader.md](reader.md)**. Streaming vs whole-buffer, row-objects vs columnar,
  fixed vs runtime schema, and the per-type reader reference.
- **Encoding JS values into a `RowBinary` payload** to send to ClickHouse →
  **[writer.md](writer.md)**. The `Sink`/`writeX` building blocks, `writeRows`
  streaming, and the per-type writer reference.

The per-type code is real, split by direction under `src/readers/` and
`src/writers/`.

## First: is RowBinary even the right format?

RowBinary exists for throughput, but it is **not automatically the fastest
path** — match the format to the shape of the data before committing to a
bespoke parser.

**Prefer a `JSON*` format (e.g. `JSONEachRow`) when** the result is mostly
strings / JSON-like values that you consume wholesale — randomly accessing
essentially every field, running string/regexp methods on them, treating values
as text. V8's native `JSON.parse` is heavily optimized C++ and builds JS strings
and objects faster than a JS-level RowBinary decoder can; pair it with HTTP
response compression (`gzip` / `zstd`, which crushes JSON's repetitive keys) and
the wire cost shrinks too.

**RowBinary clearly wins when** the result is dominated by:

- **Wide numerics** — `Int128`/`Int256`/`UInt128`/`UInt256`,
  `Decimal128`/`Decimal256`.
- **Binary / fixed-width blobs** — `IPv4`, `IPv6`, `UUID`, `FixedString`.
- **High-volume fixed-width numeric columns** generally, where each value is a
  single `DataView` read.

**Prefer the `Native` format when** columnar load and client-side analytics are
the main goal (fold/scan/filter columns, feed typed arrays to a Worker or WASM).
`Native` is column-major, so it loads straight into one typed array per column
with no transpose.

For help choosing and consuming a `JSON*` format (or CSV / TSV) instead, use the
**`clickhouse-js-node-coding`** skill.

## Core guidance (both directions)

These principles apply whether you are generating a reader or a writer; the
side-specific operational guidance is in [reader.md](reader.md) /
[writer.md](writer.md).

- **Little-endian only.** RowBinary is little-endian; target x86/ARM. Read and
  write every multi-byte number with `DataView` accessors passing a **literal**
  `true` for the `littleEndian` flag.

- **Correct first, then optimize.** First emit a correct codec built from the
  plain per-type API. Only after it's correct (and tested) specialize it. Don't
  bake performance assumptions in before correctness.

- **Monomorphize generic/composite types.** Emit specialized, inlined code per
  type combination instead of passing functions as arguments where the type is
  known ahead of time.

- **Inline the leaf ops.** The per-type `readX`/`writeX` functions are the
  correct, composable reference; the generated codec should INLINE their bodies,
  not call them, so the row loop is straight-line with no per-field indirection
  (and so the fixed-width coalescing can fold the offset arithmetic together).

- **Annotate the type per column.** Inlining erases the type structure, so put a
  short comment above each column's encode/decode block naming the ClickHouse
  type it handles.

- **Shared scratch is not reentrant.** Some hot methods reuse a module-level
  scratch buffer as a write-then-read pair — correct only because the access is
  fully synchronous. An `async`/`yield` boundary between populating and reading
  it corrupts the value.

- **TypeScript by default.** Generate TypeScript code and helpers unless the user
  explicitly asks for plain JavaScript.

## Worked examples

Six end-to-end examples with real speedup are catalogued in [EXAMPLES.md](EXAMPLES.md).

## Out of scope

- **JSON / CSV / TSV / Parquet parsing** → use `clickhouse-js-node-coding`.
- **Connection errors, hangs, type mismatches** → use
  `clickhouse-js-node-troubleshooting`.
- **Browser / Web Worker / Edge** → `@clickhouse/client-web`.

## Still Stuck?

- [ClickHouse RowBinary format](https://clickhouse.com/docs/interfaces/formats#rowbinary)
- [ClickHouse data types](https://clickhouse.com/docs/sql-reference/data-types)
- [ClickHouse JS client docs](https://clickhouse.com/docs/integrations/javascript)
