01 / BYTE-LEVEL SPECIFICATION

Four files.
No data header.

The shared RIDA file format stores field values as independent blocks. The data file begins with the first value byte; every boundary comes from the index held by the reader.

01
Data.rida

Field values, and nothing else.

Upload this one to the publisher's server or CDN.

02
Index.rida

The address catalog.

Stays with the reader: record count, codec, lengths, flags and digest.

03
Map.json

Names behind numbered IDs.

Optional plain JSON for folder names and field names.

04
Key.rida

A 256-bit AES key.

Only for encrypted builds. Keep it private.

VALUE PIPELINE

JSON bytes become a range.

Each value is compact JSON, then a raw deflate stream, then optionally sealed with AES-256-GCM. Compression must happen first because ciphertext does not compress.

JSON bytes  →  deflate  →  [ AES-256-GCM ]  →  stored bytes
Why raw deflate?

The gzip wrapper adds 18 bytes per value: magic, time, OS metadata and a CRC that RIDA does not need. The codec already lives in the index.

INDEX HEADER
BytesFieldMeaning
0–7magicRIDAIDX1
8–11index_version1
20–23record_countRecords in the file
24–31data_lengthExact data file size
32–35codec_code1 deflate, 2 plain
36–39flagsBit 0 means encrypted
40–71data_digestSHA-256 or zeros
HOW A LOOKUP WORKS

The index answers before the network.

01

Read the row offset for the requested record.

02

Walk the row to the wanted field and accumulate its position.

03

Add that position to the record's data start and read its length.

04

Ask the server for exactly that byte range; decode locally.

GUARANTEE

One request per lookup.

Opening the dataset costs zero requests. A single field costs one range request.

GUARANTEE

Whole or refused.

Failed decryption or decompression is caught before JSON is parsed.

GUARANTEE

Schema is fixed.

Changing the field set is a rebuild; that is what keeps lookup at one request.

The map gives numbered folders their names

The index holds byte addresses. The map holds the names behind numbered folder prefixes and field IDs. These are separate jobs. A folder build can produce a map like this:

{
  "version": 1,
  "records": 600,
  "paths": { "1": "catalog", "1/1": "products", "1/1/1": "items" },
  "fields": { "1": "title", "2": "price", "3": "description" }
}

The reader can resolve a name such as catalog/products/5 to the numbered record. A map is optional: datasets whose IDs already are their record names need none. When a folder map is unavailable, use the numbered IDs.

data.get("1/1/1/5", "title")
data.get("catalog/products/5", "title")
data.resolve("catalog", "products")
data.records_under("1/1")
data.folders()

For the conventional record subfolder, the name lookup can omit that level. Naming a folder without a record number returns its first record. Keep the map beside the reader’s dataset files when using name lookups.

NEXT

Turn records into these files.

Read the build guide