See it in action on the hev-shop demo store.

API

Write & Stage

Layer stamps every row-producing write with _hevlayer_upserted_at and mirrors it to the document cache. The stamp is what holds the read watermark; the full set of reserved attributes Layer manages on a row lives in the document model.

Status

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

  • 200 OK — applied upstream and stamped.
  • 422 Unprocessable Entity — Layer rejected the body before forwarding: no recognized native write operation, a reserved _hevlayer_* attribute name, or a removed custom-write key. The body is a Layer error ({ "error": "validation_error", … }), not a Turbopuffer one.
  • Upstream passthrough — any non-2xx Turbopuffer returns is relayed verbatim, including a failed conditional write (upsert_condition, patch_condition, delete_condition).
  • 502 Bad Gateway — Layer could not reach Turbopuffer ({ "error": "upstream_error", … }); the write did not apply.

Stage

Stage caches a document before it’s upserted upstream into your vector store. That O(1) read/write is especially useful for queuing chunks in a two-stage pipeline, where a CPU worker stages chunks and a GPU worker reads them back to write vectors. Staged documents are ephemeral until they’re upserted, though — a Layer document cache outage loses anything still staged.

await client.put_pipeline_document_chunks("product-images", "asin-B08N5WRWNW", {
    "chunks": [
        {"id": "asin-B08N5WRWNW-0", "text": "Wireless noise-cancelling headphones"},
        {"id": "asin-B08N5WRWNW-1", "text": "40-hour battery life", "metadata": {"page": 2}},
    ],
})
client.PutPipelineDocumentChunks(ctx, "product-images", "asin-B08N5WRWNW", &hevlayer.PutChunksRequest{
    Chunks: []hevlayer.Chunk{
        {ID: "asin-B08N5WRWNW-0", Text: "Wireless noise-cancelling headphones"},
        {ID: "asin-B08N5WRWNW-1", Text: "40-hour battery life", Metadata: map[string]interface{}{"page": 2}},
    },
})
await client.putPipelineDocumentChunks("product-images", "asin-B08N5WRWNW", {
  chunks: [
    { id: "asin-B08N5WRWNW-0", text: "Wireless noise-cancelling headphones" },
    { id: "asin-B08N5WRWNW-1", text: "40-hour battery life", metadata: { page: 2 } },
  ],
});
curl -X PUT "$LAYER_GATEWAY_URL/v2/pipelines/product-images/documents/asin-B08N5WRWNW" \
  -H "Authorization: Bearer $LAYER_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chunks": [
      {"id": "asin-B08N5WRWNW-0", "text": "Wireless noise-cancelling headphones"},
      {"id": "asin-B08N5WRWNW-1", "text": "40-hour battery life", "metadata": {"page": 2}}
    ]
  }'

Staging stores chunks in the Aerospike document cache and marks the document pending. Re-staging the same document ID replaces the chunks and resets state to pending. The full pipeline API is documented under Pipelines.

esc