Things You Can Do with a Debugger but Not with Print Debugging Published June 21, 2025 Tag: Developer Tools Debuggers are often underused despite their powerful features, partly due to setup complexity and limitations in remote environments (like Kubernetes). Many developers rely on print or log debugging, but debuggers offer unique advantages that are hard to replicate. --- Debuggers Let You See All the Way Up the Call Stack View all callers in the call stack. Inspect variables and state at each frame. Understand how you reached a particular code point by selecting parent frames. Debuggers Can Evaluate Expressions Dynamically Evaluate expressions involving function calls on the fly. Modify the running program's state interactively. Acts like a REPL with full access to current program state. Debuggers Can Catch Exceptions at the Source Use exception breakpoints to stop exactly where exceptions are thrown. Inspect program state at the exception point to diagnose the root cause. Optionally break only on uncaught exceptions. You Can Alter the Course of Execution Without Modifying Code Change variables or inputs (e.g., redirect a URL) during debugging. Avoid making permanent code changes that risk accidental commits. Test fixes or scenarios dynamically in real time. Using a Debug Configuration Standardizes the Project Setup IDEs like VSCode and IntelliJ allow debug configuration files to be checked into source control. Configurations can specify .env files, environment variables, and CLI arguments. Having debug configs for every app entry-point helps new contributors quickly start debugging and developing. --- Conclusion While many understand simple features like conditional breakpoints, more advanced debugger capabilities often go underutilized. Time Travel Debuggers (TTD) offer reversible debugging but are not widely supported in most languages yet. For more, see the author's related post: On how to debug arbitrary function calls from an IPython REPL in VSCode debugger