Staging — blog preview only.
Skip to content

Replica batch under the hood — packet shapes

Scheduled

8 min read By NT²

Blind sync is easier to trust when you can picture the packet. The edge sees shapes, sizes, and progress—not titles, notes, or a searchable attic of your secrets.

Replica batch under the hood — packet shapes

Earlier posts argued the boundary in plain language: Premium sync is a blind relay, and each vault identity gets a dedicated edge hub that coordinates replicas without opening them. This essay goes one level deeper—what a replica batch looks like on the wire—without turning the blog into a guided tour of internal modules.

The claim is simple enough to hold in one sentence:

To the edge, a replica batch is a packet of opaque frames plus the outer facts needed to store, order, and deliver them. Item fields, search indexes, and decryption keys stay on authorized devices.

If you can keep that picture, most “can the server see X?” questions answer themselves.

The constraint: readable sync JSON is the wrong packet

The tempting sync packet looks like application JSON.

A client posts an array of objects with titles, categories, usernames, note bodies, and attachment names. The server validates fields, writes columns, builds indexes, and returns the same shape to every other device. Conflict resolution becomes a server-side merge of readable records. Support can open a row. Product can search the corpus. Analytics can count how many passport-shaped items exist.

That packet shape is productive for a cloud-owned database. It is fatal to a blind vault relay.

Once the wire format is “item fields the service understands,” the service has already become a second vault—whether or not the marketing page says zero-knowledge. Encryption in transit does not help: TLS protects the path, not the application that terminates it. Disk encryption on the provider does not help: the application still sees plaintext when it parses the body. “We encrypt at rest with our key” does not help either: a key held beside the data is not a boundary between you and the operator.

Client-side encryption only repairs the model if the packet itself stops carrying readable secrets. If encrypted blobs travel next to plaintext titles, previews, deterministic search tokens, or category labels the operator can filter on, the relay is only partially blind. The interesting fields have already leaked into the schema the edge is allowed to understand.

So the design problem is not “add an encryption library to a conventional sync API.” It is refuse the conventional packet. The unit of sync must be something the edge can route without interpreting vault meaning.

Design: outer envelope versus inner attic

NT² packages cross-device changes as replica batches. Think of a batch as a sealed courier bag, not as a spreadsheet of your assets.

On the device that already holds the unlocked vault:

  1. Local changes land in the ordinary vault database—structured rows, local indexes, attachment ciphertext beside metadata.
  2. Before anything is eligible for Premium sync, sensitive content is encrypted on that device.
  3. The client builds a batch whose meaningful payload is opaque frames: byte sequences the edge can store and return, but cannot usefully parse as item fields.
  4. The batch also carries outer coordination facts—enough ordering and progress metadata for another replica to ask “what am I missing?” without asking “what changed in English?”

On the edge:

  • A Durable Object keyed by the vault’s public cryptographic identity (its Vault Key DID) acts as the per-vault sync hub: authorize the session, accept or return batches, advance coordination state, and notify connected replicas that later progress exists.
  • Cloudflare R2 object storage holds the larger ciphertext blobs—opaque frames and attachment bytes—under identifiers that are not derived from readable titles.
  • The account database holds billing and entitlement facts, public verification material, and service flags. It does not hold a second copy of your note bodies.

On the receiving device:

  1. Authenticate to the same identity.
  2. Pull batches after the last known progress point.
  3. Verify and decrypt locally.
  4. Merge into the local replica with the same rules every authorized client uses.
  5. Rebuild or update local search indexes from decrypted data—never upload a provider-readable search corpus.

One table is enough to keep the layers straight:

LayerWhat it may knowWhat it must not know
On-device vaultTitles, payloads after unlock, FTS indexes, attachment plaintext while openNothing the edge needs in order to sync
Replica batch (wire)Opaque frame bytes, sizes, ordering / progress hints, opaque object referencesReadable item fields, notes, credential secrets, attachment filenames as free text
Edge hub + object storeWhich identity owns the objects, entitlement, delivery progress, byte countsHow to decrypt a frame; what category or title it represents
Account metadataKey DID, Premium flags, billing email for receipts, disable bitsKDF salt, password verifier, master password, wrapped vault key material used for offline unlock
flowchart LR
  A[Device A<br/>encrypt locally] -->|push opaque batch| H[Edge hub]
  H --> R[(Object store<br/>ciphertext blobs)]
  H -->|progress notify| B[Device B]
  B -->|pull opaque batch| H
  B --> B2[Decrypt and merge<br/>on device]

The diagram is intentionally boring. Boring is the point. There is no step where the hub “opens the item,” “indexes the title,” or “renders a preview for support.”

Full versus delta, without turning the edge into an editor

A first enable often pushes a full batch so the cloud hub holds a complete encrypted meeting point for other devices. Ongoing work prefers delta batches: only what changed since the last acknowledged progress. Either way, the edge still sees packets and progress—not a mutable spreadsheet of secrets.

Live notification stays thin on purpose. A connected replica may learn that progress advanced past a watermark. The notification does not include the secret. The device then fetches the opaque batch over the authenticated sync path. A missed ping is an inconvenience; the next pull can catch up from durable progress state. Offline remains valid: devices that slept through every notify still reconverge when they next authenticate and sync.

Attachment bytes follow the same honesty. Large ciphertext does not need to ride inside every batch body. Metadata that names an opaque blob can travel with the replica; the blob itself lives in object storage. The store returns bytes to authorized requests. It does not need a content-type that means “passport scan, page 2.”

The trade-off: the edge cannot be your second brain

Choosing opaque packets gives up conveniences that cloud-first products treat as table stakes.

The provider cannot search your secrets while your laptop is closed. There is no honest server-side full-text index of titles and notes, because building one would require uploading readable text or a provider-readable token stream. Conflict meaning and schema evolution must be something authorized clients can apply. Support cannot open a record to tell you why a note “looks wrong.” Product analytics cannot answer “how many bank items does the average vault hold?” from the sync plane.

Metadata still exists. The edge can observe that an identity synchronized at a time, transferred a volume of bytes, or has multiple active replicas. Traffic analysis and endpoint compromise remain separate problems from “can an operator read the note.” Zero-knowledge narrows what the sync service is for; it does not abolish systems security or the physics of networks.

There is also a product trade-off users feel directly: sync is optional Premium, not the definition of owning a vault. Offline create / read / update / delete stays the happy path. The same sealed-batch idea appears in portable backup: you can move an encrypted replica between devices without ever enabling the cloud hub. The wire shape is a transport concern; the cloud is one meeting point, not the owner of truth.

What we refuse

Architecture is clearer when refusal is explicit.

No server-side plaintext search. Search belongs on an unlocked device that already holds the attic. Uploading titles, note excerpts, or a provider-readable search index would make a cloud search box easier to ship—and would create exactly the corpus a blind relay is supposed to avoid.

No operator “view vault” console. Operations need health signals: entitlement failures, transfer errors, object counts, delivery lag. They do not need a button that decrypts a customer’s frames. If that button can exist, the provider has a key or a path to one, and “opaque packet” was theater.

No treating sync frames as readable JSON item fields. The batch is not a REST resource whose body is { title, username, password, notes }. Parsers on the edge validate outer envelope and authorization. They do not grow columns for “just the category” or “just the list preview.” Every such column is a permanent expansion of what the service is allowed to know.

Those refusals are not backlog items. They are the packet contract.

Keep the packet boring

Blind sync stops being a slogan when you can describe the packet without mentioning your secrets.

Devices encrypt first. Batches carry opaque frames and progress. The edge hub—one Durable Object per Vault Key DID—coordinates delivery. Object storage keeps ciphertext blobs. Account tables keep identity and billing facts. Decryption, merge, and search happen again only on devices that already earned the keys.

For the first-pass boundary essays this deepens, start with Blind replica sync on the edge and One sync hub for one vault identity. For unlock versus cloud login, see Unlocking a local vault is not logging in to the cloud. For why the account table has nothing useful to steal for offline unlock, read No password oracle in D1. For the wider Workers surface, What the Workers are allowed to see. Offline as the default path remains Offline is the happy path.

If that packet shape matches how you want sensitive records to travel—when they travel at all—open NT² Vault.

Last updated 2026-11-12

Related stories