Even a well-tested Express app eventually needs debugging in the moment, a route behaving unexpectedly, a hanging request, a mysterious 500 error. This lesson covers the tools and techniques for finding out what's actually happening.
Request Logging as a First Line of Defense
morgan is the most common HTTP request logger for Express, printing method, path, status code, and response time for every request, an essential first signal when something isn't behaving as expected.
Combined with structured console.error() (or a real logger, covered in the Logging lesson) around error-handling middleware, request logs are often enough to pinpoint which route and status code is involved before digging further.
const morgan = require('morgan');
app.use(morgan('dev'));
// GET /users 200 12.345 ms - 128
// POST /users 400 3.201 ms - 42
The 'dev' format is colorized and concise, ideal for local development; use 'combined' for more detailed production-style logs.
Using Node's Built-In Inspector
node --inspect server.js
node --inspect-brk server.js # pauses on the first line
# then open chrome://inspect in Chrome, or attach your editor's debugger
--inspect exposes a debugging port you can attach Chrome DevTools or an IDE debugger to.
--inspect-brk pauses execution immediately, useful for catching startup-time bugs.
Set breakpoints directly in your editor (most support Node debugging natively) instead of scattering console.log() everywhere.
The debug npm module lets you enable namespaced debug output via the DEBUG environment variable.
Debugging Cheatsheet
Common debugging tools and when to reach for each.
Tool
Best For
morgan
Quick visibility into every request's method, path, and status
console.error(err.stack)
Immediate error visibility in error-handling middleware
node --inspect
Step-through debugging with breakpoints
debug module
Namespaced, toggleable debug logging via DEBUG=app:*
npm run dev + nodemon
Fast iteration loop while diagnosing an issue
Diagnosing a Hanging Request
A request that never resolves almost always traces back to a missing next() call somewhere in the middleware chain, or a promise that's never awaited or resolved. Add temporary logging at the start of every middleware suspected in the chain to see exactly where execution stops.
app.use((req, res, next) => {
console.log('logger middleware entered');
next();
});
app.use((req, res, next) => {
console.log('auth middleware entered'); // if this never logs, the previous middleware is the culprit
next();
});
Using the debug Module
The debug module (which Express itself uses internally) lets you sprinkle namespaced debug statements throughout your code that stay silent by default, and can be selectively enabled via an environment variable without touching code.
const debug = require('debug')('app:orders');
exports.createOrder = async (data) => {
debug('creating order with data: %o', data);
// ...
};
Run with DEBUG=app:orders node server.js to see just that namespace's output, or DEBUG=app:* for everything.
Common Mistakes
Leaving stray console.log() statements scattered through production code instead of using a namespaced logger.
Debugging a hanging request by guessing instead of adding step-by-step logging through the middleware chain.
Not enabling request logging (morgan) at all in development, missing an easy first signal.
Reaching for a full debugger before trying simpler, faster tools like targeted logging.
Key Takeaways
morgan gives quick visibility into every request's method, path, status, and timing.
Node's built-in --inspect flag enables real breakpoint debugging via Chrome DevTools or your editor.
The debug module supports toggleable, namespaced logging without permanent console.log() clutter.
Hanging requests almost always trace back to a missing next() or an unresolved promise.
Pro Tip
When a request hangs with no error and no response, add a log statement to the very first line of every middleware in the suspected chain, the last one to log before it stalls tells you exactly where to look.
You now have practical debugging techniques. Next, learn how to optimize Express applications in the Express Performance lesson.