Delivery guarantees & Collector

What the SDK guarantees

The Respan SDKs follow the OpenTelemetry standard: spans are batched in memory and exported in the background, the exporter retries 429, 502, 503 and 504 responses with exponential backoff, and flush() / shutdown() drain the queue before your process exits.

The SDK never writes to disk. That is deliberate: nothing accumulates on your machine, and there is no local journal to clean up. The trade-off is a small loss window:

SituationOutcome
Blip of a few secondsabsorbed by retries
Outage longer than the retry windowspans still queued are dropped
Process crash before flushthe in-memory queue is lost

For most applications this is the right default. For long-running agents that must not lose spans, add the Respan Collector.

The Respan Collector

The Respan Collector is the upstream OpenTelemetry Collector packaged with a Respan configuration. It runs next to your application, receives spans on localhost, and forwards them to Respan through a persistent, bounded queue:

  • Batches are written to a write-ahead log on disk before export and deleted the moment Respan acknowledges them. In normal operation the directory is nearly empty.
  • If Respan is unreachable, the queue grows only up to a configured cap (512 MiB by default). Beyond the cap new batches are dropped and counted, so the disk never fills up.
  • Retries never give up, and the queue survives collector restarts and host reboots.

Verified with a real outage test: spans sent while the backend returned 503 were persisted, survived a kill -9 of the collector, and were delivered after it restarted.

1

Start the collector

$export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
$docker compose -f collector/docker-compose.yaml up -d
2

Point the SDK at it

$export RESPAN_BASE_URL=http://127.0.0.1:4318

That is the only application-side change. The SDK posts to <RESPAN_BASE_URL>/api/v2/traces; the collector receives on that path and forwards to https://api.respan.ai/api/v2/traces with your API key. For the pi coding agent, respan integrate pi --with-collector writes the base URL into its config.

3

Monitor it

Scrape http://127.0.0.1:8888/metrics and alert on otelcol_exporter_enqueue_failed_spans (spans dropped because the cap was hit). otelcol_exporter_queue_size rising means Respan is unreachable and the queue is doing its job. Health: GET http://127.0.0.1:13133.

Configuration

VariableDefaultMeaning
RESPAN_API_KEYrequiredSent as Authorization: Bearer …. Read from the environment, never written to a file.
RESPAN_COLLECTOR_EXPORT_URLhttps://api.respan.ai/api/v2/tracesIngest endpoint (self-hosted / EU deployments).
RESPAN_COLLECTOR_MAX_SIZE_BYTES536870912Disk cap for the queue.
RESPAN_COLLECTOR_QUEUE_SIZE10000Maximum batches kept while Respan is unreachable.
RESPAN_COLLECTOR_DATA_DIR/var/lib/otelcol/respanQueue directory (a named volume in Compose).
RESPAN_COLLECTOR_LISTEN127.0.0.1:4318OTLP/HTTP receiver.

Sizing the cap

Disk usage during an outage is min(outage duration × ingest rate, cap). For agents producing about 5 GB of trace data per day:

CapOutage covered before drops begin
512 MiB (default)~2.5 hours
2 GiB~10 hours
5 GiB~1 day

Duplicates on retry

Retries re-send whole batches, so a batch that timed out after Respan had already stored it arrives twice. The trace view shows one span per span id, but cost and token aggregates for those runs can be double-counted until ingest de-duplicates by span id. The 30-second exporter timeout keeps this rare.

Security

The receiver, health and metrics listeners bind to loopback by default; anything that can reach the receiver can write traces into your project. The API key is read by the collector process from the environment and never written into the configuration file or the image.