---
title: "Log drains"
description: "Send every line your services write on to Datadog, Better Stack, Axiom, any HTTPS endpoint, an S3 bucket or one of your Alf buckets, about a minute after it's written."
url: "https://runalf.com/docs/log-drains"
section: "Watching"
---

# Log drains

A log drain sends every line the organization's services write on to where you keep logs already, about a minute after it's written. Add one under **Settings → Log drains** (admins), or from the [command line](https://runalf.com/docs/cli):

```bash
alf drains add datadog --api-key …              # --site datadoghq.eu for the EU
alf drains add betterstack --token …
alf drains add axiom --token … --dataset shop
alf drains add https --url https://logs.example.com/in
alf drains add s3 --bucket my-logs --region eu-central-1 --access-key-id … --secret-access-key …
alf drains add bucket --bucket logs             # one of your Alf buckets
alf drains test datadog                         # a test line, now
alf drains                                      # each one, and how it's doing
```

Keys left out are asked for at a terminal without being shown, and aren't shown again afterwards. `--project` keeps a drain to one project's services.

## What arrives

Each line with where it came from:

```json
{"at": "2026-10-30T13:04:05.123456789Z", "service": "web", "service_id": "svc_…", "project": "shop", "stream": "stderr", "server": "srv_…", "container": 1, "line": "TypeError: …"}
```

| Drain | How |
| --- | --- |
| Datadog | Its logs intake (`ddsource: alf`, the service as `service`, `project:` and `stream:` as tags). |
| Better Stack | Its HTTP source, with `dt` and `message`. |
| Axiom | The dataset's ingest, with `_time` and `message`. |
| HTTPS | A `POST` of NDJSON (one line as above per line of the body), with `X-Alf-Signature: sha256=…`, an HMAC-SHA256 of the body with the secret shown once when the drain is added. |
| S3, an Alf bucket | One gzipped NDJSON file per delivery, under `<prefix><date>/`. Any S3: `--endpoint` for one that isn't AWS (Cloudflare R2, MinIO and the like). |

## When it fails

A drain that can't deliver tries again later, waiting longer each time, up to an hour. After a day of failing it's switched off, and the organization hears about it (the **A log drain kept failing** notification). **Switch on** (or `PATCH /log-drains/{id}` with `enabled: true`) carries on from where it stopped: lines are kept three days, so a drain off for longer misses the oldest.

## Good to know

- A new drain starts with what's written after it's added, not with the days before.
- A line is sent at least once: if an answer gets lost on the way back, it may arrive twice.
- What a drain sends is kept by the other side as long as you have it keep it; Alf keeps its own [7 or 30 days](https://runalf.com/docs/metrics-and-logs#looking-back) whatever the drains do.
