Why I Stopped Using Breakpoints (Most of the Time)
There is a divide in the developer world. On one side: the debugger purists who insist you must use breakpoints, watch variables, and step through code line by line. On the other side: the chaos monkeys typing console.log("here"), console.log("here 2"), and console.log(wtf_is_this).
For years, I felt guilty about belonging to the second group. But recently, I stopped apologizing for it. Because for a large percentage of problems, console.log is actually better.
The Problem with the Debugger
Traditional debuggers are powerful, but they have a few massive drawbacks:
- Context Collapse: When you pause execution, the application state is frozen. This is great for a single moment in time, but terrible for understanding flow. How did this state evolve over the last 10 frames? A debugger gives you a snapshot; logs give you a timeline.
- Setup Friction: Setting up a debugger for a complex full-stack app (frontend, backend, database, maybe a queue) is often more painful than fixing the bug itself.
- The "Step Over" Trap: How many times have you accidentally stepped over the function you needed to step into, forcing you to restart the whole multi-minute reproduction process?
When Logging Wins
console.log (or console.table, console.trace) excels when you need to understand the sequence of events.
If a React component is re-rendering 15 times, a breakpoint will drive you insane. You have to hit "play" 15 times, trying to keep the differences in your head.
A well-placed console.log('Render', { props, state }) lets you look at the console and instantly see the timeline. You can spot the exact render where props.user suddenly turned into undefined.
The Real Alternative: Write a Test
When console.log isn't enough, my next step still isn't usually the debugger. It's a unit test.
If a pure function is returning the wrong output, don't spin up the whole app and click through the UI to trigger it. Write a test case that passes the exact inputs causing the failure. Now you have a reproducible, isolated environment.
And yes, sometimes inside that test, I will finally pull out the debugger.
The Verdict
Debuggers are essential for tracking down memory leaks, complex asynchronous deadlocks, or deeply nested library code where logging isn't an option.
But for your day-to-day work? Don't let the purists shame you. console.log("here") is a perfectly valid tool. Just remember to take them out before you commit.