API

Backend

Write

On a Postgres-backed namespace, conditions use the query filter syntax and are evaluated against each targeted row’s stored value in the write’s transaction:

  • upsert_condition: an existing row is replaced only if it passes. A new id is always inserted. A $ref_new value reads the row being written, where a missing attribute is null. ["id", "Eq", null] inserts without overwriting, and this condition keeps only newer versions:

    ["version", "Lt", {"$ref_new": "version"}]
  • delete_condition: a row is deleted only if it passes. $ref_new is null for every attribute, and a missing id is skipped.

  • rows_affected counts only the rows whose condition passed.

  • A condition on an undeclared attribute, or a $ref_new whose type differs from the compared attribute, is a 400 validation error. The whole write is rejected with no effects.

Conditional writes: approximate — upsert_condition and delete_condition, including $ref_new; patch_condition returns 422 because row and column patches are unsupported

Layer stamps every row-producing write with _hevlayer_upserted_at for supported stores. The stamp is what holds the read watermark; the full set of reserved attributes Layer manages on a row lives in the document model.

To branch or copy a namespace, see Branching.

Status

Layer validates the body before forwarding and can fail independently of the backing store, so the write path carries a few statuses a plain proxy wouldn’t:

  • 200 OK — applied to the store and stamped.
  • 422 Unprocessable Entity — Layer rejected the body before forwarding: no recognized native write operation, a reserved _hevlayer_* attribute name, a removed custom-write key, or a schema type the configured store cannot represent. The body is a Layer error ({ "error": "validation_error", … } or { "error": "UnsupportedByStore", … }), not a store one.
  • Upstream passthrough — any non-2xx the backing store returns is relayed verbatim.
  • 502 Bad Gateway — Layer could not reach the backing store ({ "error": "upstream_error", … }); the write did not apply.

The passthrough case includes a failed conditional write (upsert_condition, patch_condition, delete_condition) — turbopuffer’s error body comes back untouched.

esc