Stop Putting dd() Everywhere Debug the Database From the Source Instead

Published: (May 20, 2026 at 05:33 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

The Problem with Scattering dd() and Logs

Every backend developer has been there: a request fails, something isn’t inserted into the database, and the codebase quickly turns into a sea of debugging statements:

dd($request->all());
dd($user);
dd($campaign);
Log::info($query);

Logs are added in controllers, services, repositories, queue workers, and event listeners. After hours of digging, you’re still confused because the real problem isn’t where you’re looking.

A Real‑World Example

A few months ago a team faced a strange issue with a simple form submission that should:

  1. Create a user
  2. Assign a campaign
  3. Generate a lead
  4. Push a welcome email into a queue
  5. Write an activity log

Randomly, some users were created without campaign data. Sometimes the queue job ran, sometimes it didn’t, and occasionally the transaction rolled back silently.

The first reaction was to sprinkle logs everywhere:

// Controllers
Log::info('Controller hit');

// Services
Log::info('Campaign assigned');

// Queue workers
Log::info('Email queued');

// Transactions
DB::beginTransaction();

The code became a forest of debugging statements, yet no clear answer emerged.

The Missing Insight: The Database Is the Single Source of Truth

No matter how beautiful your architecture is—whether you use Laravel, raw PHP, Node.js, Python, or Java—every query ends up in one place: MySQL. The database sees everything, and that realization changes how you debug.

Enabling the General Query Log

SET GLOBAL general_log = 'ON';

Then watch the live log:

tail -f /var/lib/mysql/hostname.log

You’ll see the exact sequence of statements:

INSERT INTO users ...
UPDATE campaigns ...
ROLLBACK;

In the example above, the ROLLBACK revealed that another process had locked a table for a few seconds—something no controller log could have shown.

Why Debugging Inside the Application Often Misses the Real Issue

A single request may involve:

  • Queues
  • Events
  • Transactions
  • Scheduled jobs
  • Caching
  • Background workers
  • Third‑party APIs

By the time you debug from inside a controller, the actual problem may already be happening elsewhere (deadlock, lock wait, slow query, missing index, transaction conflict, etc.). MySQL already knows all of this.

Four Essential MySQL Features Every Backend Developer Should Know

1. General Query Log

SET GLOBAL general_log = 'ON';

Use case: Watch every query in real time, especially when a request touches multiple tables or when hidden ORM queries are suspected.

Remember: Disable it after debugging to avoid massive logs and performance impact.

SET GLOBAL general_log = 'OFF';

2. Slow Query Log

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;   -- log queries slower than 1 second

Use case: Identify missing indexes, N+1 problems, huge table scans, and inefficient joins.

Example: A dashboard dropped from 12 seconds to under 800 ms after the slow query log exposed a missing index.

3. InnoDB Engine Status

SHOW ENGINE INNODB STATUS;

Use case: When you experience hanging requests, frozen queues, stuck inserts, or transaction conflicts, this command reveals the latest deadlock or lock‑wait information.

4. Triggers for Auditing

Create database‑level audit trails that are framework‑independent.

CREATE TRIGGER users_after_insert
AFTER INSERT ON users
FOR EACH ROW
INSERT INTO audit_logs(table_name, action_type)
VALUES ('users', 'INSERT');

Benefits: Automatic tracking of who changed data, when, which table, and what action—without relying on application logs.

Best Practices

  1. Enable logs only when needed. Turn on general_log or slow_query_log temporarily, investigate, then disable.
  2. Monitor log size and performance. Permanent logging can quickly consume storage and degrade performance.
  3. Combine MySQL insights with application logs. Use database logs to pinpoint the root cause, then add targeted application logging if necessary.
  4. Leverage triggers for audit trails when you need reliable, framework‑agnostic change tracking.

By treating the database as the primary source of truth and using these built‑in MySQL tools, you can cut debugging time dramatically and avoid the endless cycle of sprinkling dd() and Log::info() throughout your code.

0 views
Back to Blog

Related posts

Read more »

Go Error Handling: Annoying or Awesome?

For weeks when I was completely new to coding, I kept wondering, “What did I get myself into?” I barely understood what I was looking at whenever I came across...

My first wordpress plugin

Introduction I built a free WordPress plugin to solve my content discovery problem. Content discovery was taking 2–3 hours daily, so I wanted something that li...