betterstack drain posts to one Better Stack source’s ingesting host. Records arrive with dt as the timestamp, level as the severity, message as the log line, and the whole Lua record kept alongside as structured fields you can query and alert on.
Before you begin
- A Better Stack source of type HTTP. Its Connect page gives you two things you need: the ingesting host and the source token.
What to enter
Output
Better Stack deliveries are not signed. There is no
X-Lua-Signature header and no signing secret; the Authorization header authenticates the sender. If you need a signature, use a generic HTTPS drain.How ownership verification works
Better Stack uses a test post: one batch containing a singlelua.drain.test record is sent to the ingesting host, and any 2xx is accepted.
401 means the token is wrong or is missing its Bearer prefix — the stored value is sent as the whole header value, so Bearer is part of what you enter. The drain stays in pending_verification and keeps buffering (for up to six hours) while you fix it. Verification is limited to 5 attempts per drain per hour.
What arrives
Each record becomes one entry in a JSON array:
The batch’s
resource is not flattened into each entry, so an entry carries no organization id, agent id, or agent name — only the record. Group by lua.attributes["lua.primitive.name"] for a primitive and by lua.eventName for a kind of event.
If you need the agent or the environment on every record — one source receiving several agents, for example — send to an OpenTelemetry collector instead and promote the resource attributes there. The published collector config already copies
service.name and the environment onto each record, and its exporter can forward to Better Stack.Useful queries
Caps
Test the token with curl
Prove the host and the token before creating the drain. This sends exactly the shape a delivery has:202 means accepted; the entry shows up in Live tail within a few seconds. A 401 means the token is wrong or the Bearer prefix is missing; a 404 usually means the ingesting host belongs to a different source or region.
Then do the same through the real delivery path:
Alert on it
Better Stack alerts on a saved query. Three that are worth having from day one:
The heartbeat is what makes the other two trustworthy: it arrives every five minutes while the drain is
healthy, so its absence tells you the pipeline is down rather than that your agents went quiet. Delivery guarantees explains what it does and does not prove.
If it isn’t working
401 on every delivery
401 on every delivery
The stored header value is sent verbatim as
Authorization. It must read Bearer <source token>, prefix included. Update it with lua drains update <id> --header Authorization and re-enter the whole value.404 or a redirect
404 or a redirect
The ingesting host is per-source and per-region. Copy it from that source’s Connect page. A
3xx is treated as a failure and never followed, so a host that redirects has to be replaced with its final URL.Nothing arrives although the drain is healthy
Nothing arrives although the drain is healthy
healthy means the ingesting host accepted the batch. Check that you are looking at the right source, and that the source’s retention and any archiving rule have not moved the data. lua drains deliveries <id> shows the status code and response excerpt for each recent batch.Next steps
Event schema
What every field under
lua means.Delivery guarantees
Retry, drops, heartbeat, and health states.
Ship logs to your stack
Selectors, states, and quotas.
lua drains
Every verb and flag.

