How to View Heroku Logs: heroku logs --tail and Drains
Last verified on Nov 8, 2026.
heroku logs fetches your app's recent log lines, and heroku logs --tail streams them live. Heroku keeps almost no history, so the commands below only reach back about 1,500 lines. If you need more than that, you must forward logs with a log drain or add-on. This guide covers the CLI flags, how to read a line, the platform limits, and how to keep logs.
What Heroku Logs Contain
Heroku merges output from every dyno, platform component, and add-on into one stream. Four kinds of lines end up in it:
- App logs from your code and dependencies. Anything written to stdout or stderr is captured. Filter:
--source app. - System logs from the platform acting on your app, such as restarting a crashed process or serving an error page. Filter:
--source heroku. - API logs for administrative actions like deploys, scaling, and toggling maintenance mode. Filter:
--source app --dyno api. - Add-on logs from services you attach. See each add-on's docs.
Build output is separate. Find it in the app's Activity tab, by choosing View build log on a build event.
Heroku has two platform generations with different logging. Cedar uses Logplex. Fir does not use Logplex, has no log history, and exports OpenTelemetry (OTLP) logs instead. Most of this guide notes where they differ.
Reading Logs with the CLI
# Latest logs (100 lines on Cedar)
heroku logs --app example-app
# More lines, up to 1,500
heroku logs -n 1500 --app example-app
# Live tail
heroku logs --tail --app example-app
# Only router lines
heroku logs --dyno router --app example-app
# Only your app's output, live
heroku logs --source app --tail --app example-app
# One dyno type, then one dyno
heroku logs --dyno worker --app example-app
heroku logs --dyno web.1 --app example-app--source (-s) and --dyno (-d) can be combined, and either works with --tail. A dyno filter accepts the base name (web) or the full name (web.1). A real-time tail stops by itself after one hour of inactivity.
On Fir, heroku logs defaults to a real-time tail because there is no history, and you can filter by process type:
heroku logs --process-type=web --app example-appHeroku Logs Do Not Arrive in Order
Heroku assembles one stream from many sources, and its collectors are distributed, so lines can arrive out of order. Sort by timestamp when sequence matters, and do not assume the order you see is the order events happened.
Reading a Log Line
The format is timestamp source[dyno]: message:
2010-09-16T15:13:46.698234+00:00 app[web.1]: Completed in 74ms (View: 31, DB: 40) | 200 OK
2010-09-16T15:13:46.723498+00:00 heroku[router]: at=info method=GET path="/posts" host=example-app-1234567890ab.herokuapp.com fwd="204.204.204.204" dyno=web.1 connect=1ms service=18ms status=200 bytes=975- Timestamp is RFC 5424 with microsecond precision, set when the dyno or component produced the line.
- Source is
appfor your dynos, andherokuon Cedar or aheroku-prefix on Fir for platform components. - Dyno is the process, such as
worker.3, orrouter(heroku-routeron Fir). - Message is the content. Lines longer than 10,000 bytes are split into 10,000-byte chunks, each as a separate line.
Router lines carry the useful request facts as key=value pairs: method, path, host, dyno, connect and service times, status, and bytes. They are easy to grep.
Error Codes Worth Knowing
Heroku documents every platform error in its error codes reference. The ones you meet most (see crash loops and latency spikes for detecting them early):
A quick check for them:
heroku logs -n 1500 --app example-app | grep -E 'code=H1[0-9]|R1[04]'Limits to Know
Cedar apps use Logplex, which Heroku describes as designed for collating and routing log messages, not for storage. It retains the most recent 1,500 lines of your consolidated logs for up to one week. Fir has no log history at all. Shield Spaces with Private Space Logging enabled cannot use heroku logs either, so read those logs from a log drain.
For real-time output, make sure your app does not buffer. In Ruby, set $stdout.sync = true in config.ru. Some frameworks log elsewhere by default, such as Rails with TaggedLogger, which needs config.logger = Logger.new(STDOUT). Avoid printing config var values directly, since the Common Runtime expands them in output. See log levels and structured logging for what to write.
Keeping Logs with Drains and Add-ons
To keep logs beyond 1,500 lines, send them somewhere durable. A logging add-on is the simplest on Cedar. A log drain gives you full control:
# Syslog over TLS (Cedar)
heroku drains:add syslog+tls://logs.example.com:12345 -a myapp
# HTTPS endpoint you run (Cedar)
heroku drains:add https://user:pass@logs.example.com/logs -a myapp
# See drains and their tokens
heroku drains --json -a myappSyslog drains deliver RFC 5424 messages over TCP with octet-counting framing. HTTPS drains receive batches in a POST with content type application/logplex-1, and your endpoint should answer with an empty body and a Content-Length of 0. Each log drain has a token that appears in the messages it sends, which lets you separate streams that go to the same URL. Syslog drains have no authentication, so filter out messages with unknown tokens.
On Fir, use telemetry drains, which export OTLP logs, traces, and metrics to any OTLP-compatible backend:
heroku telemetry:add --app my-app https://otlp.example.comSee log forwarding for the general pattern.
Searching Heroku Logs with Sazabi
Sazabi, an AI-native observability and security platform, can use the Heroku CLI inside its agent sandbox, so the agent can read an app's logs the way you do. Connect it under Settings > Sandbox CLIs with a HEROKU_API_KEY, or run sazabi sandbox-clis connect heroku --env HEROKU_API_KEY=<key>. Then ask the agent in a thread to run heroku logs.
Sazabi's docs list no Heroku log source, so keep your log drain or add-on as the long-term store. See the Heroku integration page. The docs for the Heroku CLI connection have the full setup.
Frequently Asked Questions
How do I tail Heroku logs?
Run heroku logs --tail --app your-app (or -t). It prints recent lines and keeps the session open for live output. Press Ctrl+C to stop. Heroku ends a tail session after one hour of inactivity.
How many lines does heroku logs show?
On Cedar apps it returns 100 lines by default and up to 1,500 with --num or -n. Logplex keeps only the most recent 1,500 lines, for up to one week, so older output is gone unless you forwarded it with a log drain.
How do I see only router logs or only app logs?
Use --source app for your own processes and --source heroku for platform components such as the router, or --dyno router for just the router. On Fir apps, filter by process type with --process-type.
How do I keep Heroku logs longer?
Add a logging add-on or a log drain. Cedar apps can use syslog or HTTPS drains, and Fir apps use telemetry drains that export OpenTelemetry logs. Heroku itself keeps no long-term history.
What does H12 mean in Heroku logs?
H12 is a request timeout: an HTTP request took longer than 30 seconds, so the router returned a 503 while the app process may still be working.
Sources
- Log categories, Cedar and Fir differences, heroku logs defaults and flags, the 1,500 line Logplex limit, tail inactivity timeout, filters, log format, out-of-order logs, and 10,000 byte chunking (accessed Nov 8, 2026)
- Syslog, HTTPS, and telemetry drains, heroku drains:add syntax, log drain tokens, and that syslog and HTTPS drains are Cedar only (accessed Nov 8, 2026)
- Fir telemetry drains export OTLP signals and are added with heroku telemetry:add (accessed Nov 8, 2026)
- H10 app crashed, H12 request timeout after 30 seconds, H18, R10 boot timeout after 60 seconds, and R14 memory quota exceeded (accessed Nov 8, 2026)
- Connecting the Heroku CLI to the Sazabi agent sandbox with a Heroku API key (accessed Nov 8, 2026)