Events model
One append-only events table is the source of truth. How an event is shaped, how events group into a trace, what gets spilled to S3, and how retention ages data out.
Everything axonpush stores is an event in one append-only table in Aurora DSQL. Traces, logs and analytics are all views over that table rather than separate stores, which is what keeps the data model small and the platform cheap to run.
An event
An event is a single fact, a model call, a tool call, an HTTP request, a log line, an error. Every event carries the identifiers that let the rest of the product reconstruct meaning from it:
| Field | What it is |
|---|---|
eventId | Server-assigned UUID for this row. |
identifier | The event’s name, e.g. web_search or chain.start. Part of the dedupe key. |
eventType | The canonical type, agent.start, agent.tool_call.start, app.log, app.span, custom, and the rest. |
payload | The free-form JSON body, subject to the telemetry policy. |
traceId | Groups every event in one request into a trace. |
spanId / parentSpanId | Position within the trace’s span tree. |
agentId, channelId, appId, orgId, environmentId | Scoping. |
createdAt | Acceptance timestamp. |
The backend also derives what it can, model attribution, token and cost
accounting, timing, and provenance, and fills those columns in when the event
carries enough to compute them. A hand-published custom event leaves most of
them unset.
Events group into a trace
A trace is every event sharing one traceId. There is no separate trace
record being written on the hot path; a trace is materialised on read by
grouping and ordering its events, then deriving a summary, duration, error
count, tokens, cost, the agents, models and tools involved.
The SDKs create and propagate a trace context for you, so events published across steps and services stitch into one trace automatically. See the traces guide.
S3 spill
Most payloads live inline in the events table. A payload larger than the inline limit is written to S3 and the row keeps a reference to it, so a single oversized tool result or minidump does not bloat every query that touches the table. The spill is transparent, the API rehydrates the payload from S3 when you read the event back, subject to the same content policy.
Attachments and minidumps have their own cap. Above roughly 1 MiB the bytes are
dropped and the record is flagged truncated: true with the real sizeBytes,
so you still see that a large payload happened without the store carrying it.
Retention
Events and traces carry a TTL and are aged out by the cron Lambda on the organisation’s retention schedule. Aggregated analytics and search projections are derived from the events table and rebuildable, so the raw retained events are the single source of truth. The audit log is the exception: audit entries carry no TTL and are never aged out.
The privacy boundary
Prompt, message, input, output and tool content is opt-in. The
organisation’s telemetry policy is applied before an event is persisted and again
before it is delivered anywhere, and its default contentCaptureMode is
metadata_only, content-bearing keys are replaced with [REDACTED] unless you
raise the mode deliberately.
| Mode | Behaviour |
|---|---|
metadata_only | Content keys (prompt, messages, completion, input, output, tool_result, …) become [REDACTED]. The default. |
redacted | Content keys are kept but truncated to a short preview. |
full | Content is kept as sent. |
Credential-shaped keys (authorization, cookie, password, secret,
api_key, access_token, …) are redacted in every mode; that is not
configurable. Read and write the policy at
PATCH /organizations/{orgId}/telemetry-policy, and mirror it client-side with
the SDK’s content_capture_mode, redact_keys and max_content_length
settings.
Related
- Architecture, where the events table sits
- Traces (Python SDK), the trace context and reading traces back
- Environments, the label every event carries
Architecture
How axonpush is built, a Go modular monolith on Lambda, a Bun auth service, Aurora DSQL as the primary store and S3 for spilled payloads. Serverless end to end, the same shape hosted or self-hosted.
Custom dimensions
Every attribute you stamp on a span or event becomes a queryable dimension. How axonpush discovers them, how to slice by them, and how to name them so they stay useful.