Skip to main content
The server keeps recorded calls, captured values and function history under separate limits. The relay manages queue files on each application host. Configure these limits for the data window and server outages you need to accommodate.

Stored execution data

A trace can outlive its captured values, and function relationships can outlive their example traces. Trace retention is measured from the server’s first receipt time, not the application’s execution start time. The function index expires inactive relationships, not individual observations in a rolling window. Counts accumulate while a relationship remains present; an active relationship can retain counts and a first observation older than 90 days.

Local queue retention and outages

The SDK never deletes queue files. If the relay is stopped, the SDK continues writing and the queue grows until storage is exhausted. A running relay manages queue cleanup and pressure retention independently of the server’s storage limits. The relay’s queue budget defaults to 2 GiB. Normal cleanup removes a fully drained hour once it is past the five-minute finality grace. Pressure cleanup can instead remove the oldest eligible hour even when it contains unsent records. Those drops are counted as daemon_spool_expired. The retention sweep runs every minute by default. The current hour and hours still inside the grace window are protected from pressure cleanup. The queue can therefore remain above its configured budget when no eligible hour remains. The budget is not a guarantee that any fixed outage duration is safe; recording volume and available disk space determine how much backlog you can retain.

Retryable failures and terminal rejection

The relay retries network failures, 429, and HTTP 500, 502, 503 and 504. Other response statuses are terminal for the batch; this includes invalid credentials and a token with the wrong role. Per-record rejections in a successful batch response are terminal for those records as well. Terminal records increment daemon_terminal_reject, then the cursor advances past them. Correcting a token or destination later does not cause those records to be retried. Raw queue files can remain until normal cleanup, but their presence does not mean they are pending. Do not reset delivery cursors or edit queue files. Use Troubleshooting to distinguish a growing backlog from records already accounted for as drops.

Value-budget enforcement

When server-side values exceed their budget, retention deletes the oldest whole hour segments of value files. A pass runs every 10 minutes and performs bounded work. This is not an exact expiry timer for each value. The write path can also retain call records while declining new value bytes under budget pressure.

Estimate capacity

Set the server’s data directory and run the capacity check using your expected sustained rate in traces per second. Replace the path below with the directory used by vexlo serve:
The check uses a fixed estimate of 28,700 value bytes per trace, not a measurement of your application. It compares the resulting value lifetime with the configured call-record retention. The default expected rate, when omitted, is 2 traces per second. At 30 traces per second, the check succeeds and reports this retention calculation (excerpt):
The check reports the estimated value lifetime even when it is shorter than call-record retention. That difference does not fail the check. Increase -value-budget-bytes to retain more values, or reduce value sampling to write fewer bytes. Both check and serve reject a budget greater than the total capacity of the value-store volume unless -allow-overcommit is set. A budget greater than current free space produces a warning.

Interpret unavailable values

Read full values through the values endpoint. Trace detail resolves a pending handle to stored when its bytes are readable, but does not recheck every previously stored handle. A preview alone does not establish that full bytes remain available. expired means that the capture record refers to bytes that are unavailable. They were either reclaimed or have not arrived. The server does not retain the arrival history needed to distinguish those causes. A pending capture becomes stored when its bytes are readable. If it remains pending, the response does not establish why the bytes are unavailable or whether a later read will find them. The recording’s completeness and root status do not resolve value availability.

Verify storage and delivery separately

Authenticated GET /v1/health reports server storage usage, budget and mode. Relay /healthz, /metrics and relay status describe the local forwarding process and queue. A healthy empty queue does not prove every record was accepted: terminal drops can leave zero backlog. Compare sent and dropped counters, then verify an identified application trace. See Configuration for exact settings and HTTP traces and values for the read contract.