Read Node.js application logs

3 min read07 November 2026

On a VPS you read logs with journalctl. On app hosting you have no root and no systemd access: the panel console shows what the process writes to stdout and stderr. Reading that stream lets you tell a code error, a missing dependency and a plain restart loop apart.

Where logs live

The service page has a console or logs tab. It receives standard output and standard error in emission order. That view is temporary: it covers the current run and the most recent messages, not a full archive. To keep history, also write to a file in the project and watch disk usage, or export regularly.

stdout, stderr and levels

console.log writes to stdout; console.warn, console.error and uncaught errors go to stderr. Both reach the console, often with no visual distinction. JSON logs stay readable by machines and humans:

JavaScript
const level = process.env.LOG_LEVEL || 'info';
console.log(JSON.stringify({ level, msg: 'server started', port: process.env.PORT }));

Choose a level per environment: info in production, debug only when needed. Libraries such as pino or winston handle levels and formatting, but a small helper is enough for a small app. Never log a token, password, cookie or full connection string. If you log headers, mask Authorization and Cookie.

Recognising a restart loop

A loop shows the same block every few seconds: startup banner, exit, return. Look for the first error after startup, not the last line, which is often a plain shutdown message.

  • Cannot find module: missing dependency or wrong MAIN_FILE.
  • SyntaxError: uncompiled file or wrong Node version.
  • ECONNREFUSED to the database: wrong host, port or credentials.
  • Exit code 137: process killed, often out of memory.
  • Code 143: platform requested shutdown (SIGTERM).

Exit code 137 deserves a memory check: a growing cache or a leak ends up triggering it even when the code looks correct.

Logging usefully

  • One line per request with method, path, status and duration, without the body.
  • A full stack trace for errors, not just error.
  • A request id to correlate lines.
  • No periodic "still alive" message drowning incidents.
  • A size cap if you write to a file.

Check

Restart, confirm a single startup block, call the health route, then trigger a handled 404: you should see one request line and no restart. If the console stays empty, check that your logger does not swallow output and that the process reaches its entry point.

Advertisement

Was this article helpful?

Read next