# Tail Workers Configuration

## Setup Steps

### 1. Create Tail Worker

Create a Worker with a `tail()` handler:

```typescript
export default {
  async tail(events, env, ctx) {
    // Process events from producer Worker
    ctx.waitUntil(
      fetch(env.LOG_ENDPOINT, {
        method: "POST",
        body: JSON.stringify(events),
      })
    );
  },
};
```

### 2. Configure Producer Worker

In producer's `wrangler.jsonc`:

```jsonc
{
  "name": "my-producer-worker",
  "tail_consumers": [
    {
      "service": "my-tail-worker",
    },
  ],
}
```

### 3. Deploy Both Workers

```bash
# Deploy Tail Worker first
cd tail-worker
wrangler deploy

# Then deploy producer Worker
cd ../producer-worker
wrangler deploy
```

## Wrangler Configuration

### Single Tail Consumer

```jsonc
{
  "name": "producer-worker",
  "tail_consumers": [
    {
      "service": "logging-tail-worker",
    },
  ],
}
```

### Multiple Tail Consumers

```jsonc
{
  "name": "producer-worker",
  "tail_consumers": [
    {
      "service": "logging-tail-worker",
    },
    {
      "service": "metrics-tail-worker",
    },
  ],
}
```

**Note:** Each consumer receives ALL events independently.

### Remove Tail Consumer

```jsonc
{
  "tail_consumers": [],
}
```

Then redeploy producer Worker.

## Environment Variables

Tail Workers use same binding syntax as regular Workers:

```jsonc
{
  "name": "my-tail-worker",
  "vars": {
    "LOG_ENDPOINT": "https://logs.example.com/ingest",
  },
  "kv_namespaces": [
    {
      "binding": "LOGS_KV",
      "id": "abc123...",
    },
  ],
}
```

## Testing & Development

### Local Testing

**Tail Workers cannot be fully tested with `wrangler dev`.** Deploy to staging environment for testing.

### Testing Strategy

1. Deploy producer Worker to staging
2. Deploy Tail Worker to staging
3. Configure `tail_consumers` in producer
4. Trigger producer Worker requests
5. Verify Tail Worker receives events (check destination logs/storage)

### Wrangler Tail Command

```bash
# Stream logs to terminal (NOT Tail Workers)
wrangler tail my-producer-worker
```

**This is different from Tail Workers:**

- `wrangler tail` streams logs to your terminal
- Tail Workers are Workers that process events programmatically

## Deployment Checklist

- [ ] Tail Worker has `tail()` handler
- [ ] Tail Worker deployed before producer
- [ ] Producer's `wrangler.jsonc` has correct `tail_consumers`
- [ ] Environment variables configured
- [ ] Tested with staging environment
- [ ] Monitoring configured for Tail Worker itself

## Limits

| Limit                           | Value                           | Notes                                        |
| ------------------------------- | ------------------------------- | -------------------------------------------- |
| Max tail consumers per producer | 10                              | Each receives all events independently       |
| Events batch size               | Up to 100 events per invocation | Larger batches split across invocations      |
| Tail Worker CPU time            | Same as regular Workers         | 10ms (free), 30ms (paid), 50ms (paid bundle) |
| Pricing tier                    | Workers Paid or Enterprise      | Not available on free plan                   |
| Request body size               | 100 MB max                      | When sending to external endpoints           |
| Event retention                 | None                            | Events not retried if tail handler fails     |

## Workers for Platforms

For dynamic dispatch Workers, both dispatch and user Worker events sent to tail consumer:

```jsonc
{
  "name": "dispatch-worker",
  "tail_consumers": [
    {
      "service": "platform-tail-worker",
    },
  ],
}
```

Tail Worker receives TWO `TraceItem` elements per request:

1. Dynamic dispatch Worker event
2. User Worker event

See [patterns.md](patterns.md) for handling.
