Skip to main content
Technology & EngineeringLogging Services197 lines

Better Stack / Logtail

Better Stack (Logtail) logging — structured log ingestion, live tail, SQL-based querying, alerting, and uptime monitoring

Quick Summary28 lines
You are an expert in integrating Better Stack (formerly Logtail) for application logging and observability.

## Key Points

1. Define a query (e.g., `level = 'error' AND service = 'payments'`).
2. Set a threshold (e.g., more than 10 matches in 5 minutes).
3. Route to Slack, PagerDuty, email, or a webhook.
- Always call `logtail.flush()` before process exit (or in serverless function handlers before returning) to avoid losing buffered logs.
- Use structured JSON fields instead of embedding data in the message string — this enables SQL querying and faceted filtering.
- Create separate sources for each service/environment in Better Stack so logs are isolated and permissions can be scoped.
- Use the SQL query interface for ad-hoc analysis and dashboards rather than relying solely on the search bar — SQL gives you aggregations, joins, and percentiles.
- Set up alerts for critical patterns early; Better Stack's integration with its own incident management product makes escalation seamless.
- Forgetting to flush the Logtail client in serverless environments (AWS Lambda, Vercel Functions), causing the last batch of logs to be lost when the function freezes.
- Using overly broad source tokens across multiple services, making it impossible to scope access or filter by source.
- Logging large binary payloads or base64-encoded data as structured fields, inflating storage costs and slowing queries.
- Not setting the `dt` field when using the HTTP API — Better Stack will use ingestion time, which may differ from the actual event time.

## Quick Example

```bash
npm install @logtail/node @logtail/winston
```

```bash
npm install @logtail/pino
```
skilldb get logging-services-skills/Better Stack / LogtailFull skill: 197 lines
Paste into your CLAUDE.md or agent config

Better Stack (Logtail) — Logging Integration

You are an expert in integrating Better Stack (formerly Logtail) for application logging and observability.

Core Philosophy

Better Stack is designed for developers who want observability without operational overhead. It combines log management, uptime monitoring, and incident management in a single platform, eliminating the need to stitch together separate tools for each concern. The value proposition is speed: fast ingestion, fast search, fast time-to-alert. If you can query your logs with SQL and get results in under a second, debugging in production becomes a routine task rather than an emergency.

Structured logging is the foundation of everything Better Stack offers. The SQL query engine, dashboards, and alerts all operate on structured fields. If you embed data in free-text message strings ("User 123 placed order 456"), that data is invisible to the query engine. Log structured JSON objects with explicit fields ({userId: "123", orderId: "456", action: "order_placed"}) so every field is searchable, filterable, and aggregable.

Separate sources per service and environment. Better Stack sources are the organizational boundary for access control, retention policies, and billing. Mixing production and staging logs in a single source makes it impossible to scope permissions, creates noise in alerts, and makes it harder to distinguish real incidents from test traffic.

Anti-Patterns

  • Embedding data in message strings instead of structured fields -- logger.info("User 123 logged in") is unsearchable. Use logger.info({userId: "123"}, "user logged in") so the userId is a queryable field.
  • Forgetting to flush the Logtail client in serverless environments -- AWS Lambda, Vercel Functions, and similar runtimes freeze execution after the response. Buffered logs that are not flushed before returning are lost.
  • Using a single source token across all services -- This prevents scoping access, makes it impossible to set per-service retention policies, and creates a noisy global log stream that is harder to query.
  • Logging large binary payloads or base64-encoded data -- Structured fields containing large blobs inflate storage costs and slow queries. Log references (URLs, IDs) to large data, not the data itself.
  • Not setting the dt field when using the HTTP API -- Without an explicit timestamp, Better Stack uses ingestion time. If there is any delay between event creation and ingestion, your timeline will be inaccurate.

Overview

Better Stack is a modern observability platform that combines log management (Logtail), uptime monitoring, and incident management. Its logging product ingests structured JSON logs via HTTP API or language-specific SDKs, stores them in a columnar database optimized for fast queries, and lets you query logs using familiar SQL syntax. Better Stack is known for its clean developer experience, generous free tier, and sub-second search performance.

Setup & Configuration

Node.js SDK

npm install @logtail/node @logtail/winston
const { Logtail } = require('@logtail/node');
const { LogtailTransport } = require('@logtail/winston');
const winston = require('winston');

const logtail = new Logtail(process.env.LOGTAIL_SOURCE_TOKEN);

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console(),
    new LogtailTransport(logtail),
  ],
});

// Structured context is automatically forwarded
logger.info('Payment processed', {
  orderId: 'ord-456',
  amount: 99.95,
  currency: 'USD',
  userId: 'usr-789',
});

// Flush before process exit
process.on('beforeExit', async () => {
  await logtail.flush();
});

Pino Integration

npm install @logtail/pino
const pino = require('pino');
const { Logtail } = require('@logtail/node');
const { LogtailStream } = require('@logtail/pino');

const logtail = new Logtail(process.env.LOGTAIL_SOURCE_TOKEN);
const stream = new LogtailStream(logtail);

const logger = pino(
  { level: 'info' },
  pino.multistream([
    { stream: process.stdout },
    { stream },
  ])
);

logger.info({ requestId: 'req-001', durationMs: 42 }, 'Request handled');

Python SDK

pip install logtail-python
import logging
from logtail import LogtailHandler

handler = LogtailHandler(source_token="your-source-token")

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logger.addHandler(handler)

logger.info("Deployment started", extra={
    "version": "2.1.0",
    "deployer": "ci-pipeline",
    "environment": "production",
})

HTTP API (Language-Agnostic)

curl -X POST "https://in.logs.betterstack.com" \
  -H "Authorization: Bearer $LOGTAIL_SOURCE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "dt": "2026-03-17T10:30:00.000Z",
      "level": "info",
      "message": "Batch job completed",
      "job_id": "batch-42",
      "records_processed": 15000
    }
  ]'

Heroku, Vercel, and Fly.io

Better Stack provides native integrations for these platforms via log drains. Configure them in the Better Stack dashboard under Sources — select the platform and follow the one-click setup flow.

Core Patterns

SQL-Based Log Querying

Better Stack stores logs in a columnar format and exposes a SQL query interface:

-- Error rate by service over the last hour
SELECT
  json_value(metadata, '$.service') AS service,
  count(*) AS error_count
FROM logs
WHERE level = 'error'
  AND dt > now() - INTERVAL 1 HOUR
GROUP BY service
ORDER BY error_count DESC

-- P95 response time from structured logs
SELECT
  percentile_cont(0.95) WITHIN GROUP (ORDER BY CAST(json_value(metadata, '$.duration_ms') AS FLOAT)) AS p95
FROM logs
WHERE json_value(metadata, '$.service') = 'api'
  AND dt > now() - INTERVAL 1 HOUR

Live Tail

The live tail view in the Better Stack dashboard streams incoming logs in real time with instant filtering. Each log entry expands to show all structured fields, making it a powerful debugging tool.

Alerting

Create alerts based on log queries:

  1. Define a query (e.g., level = 'error' AND service = 'payments').
  2. Set a threshold (e.g., more than 10 matches in 5 minutes).
  3. Route to Slack, PagerDuty, email, or a webhook.

Dashboards

Build dashboards from log data using SQL aggregations. Widgets support counters, line charts, bar charts, and tables — all driven by the same SQL query engine.

Best Practices

  • Always call logtail.flush() before process exit (or in serverless function handlers before returning) to avoid losing buffered logs.
  • Use structured JSON fields instead of embedding data in the message string — this enables SQL querying and faceted filtering.
  • Create separate sources for each service/environment in Better Stack so logs are isolated and permissions can be scoped.
  • Use the SQL query interface for ad-hoc analysis and dashboards rather than relying solely on the search bar — SQL gives you aggregations, joins, and percentiles.
  • Set up alerts for critical patterns early; Better Stack's integration with its own incident management product makes escalation seamless.

Common Pitfalls

  • Forgetting to flush the Logtail client in serverless environments (AWS Lambda, Vercel Functions), causing the last batch of logs to be lost when the function freezes.
  • Using overly broad source tokens across multiple services, making it impossible to scope access or filter by source.
  • Logging large binary payloads or base64-encoded data as structured fields, inflating storage costs and slowing queries.
  • Not setting the dt field when using the HTTP API — Better Stack will use ingestion time, which may differ from the actual event time.
  • Ignoring the SDK's built-in batching and sending one HTTP request per log line, causing rate limiting and degraded performance.

Install this skill directly: skilldb add logging-services-skills

Get CLI access →