Home / Articles / Web Development
Web Development

Is Your Website Slow? Track the Issues from Browser to MySQL

A slow web page is not always caused by hosting or database queries. By breaking down a single request into several stages, you can identify the actual bottleneck and fix it without guessing.

Website Terasa Lambat? Lacak Masalahnya dari Browser sampai MySQL

When a page feels slow, the first temptation is usually to blame the server, internet connection, or database. However, a single page request can pass through many points: the browser waits for a connection, PHP executes logic, the application calls an API, MySQL retrieves data, and then the results are rendered back to the user.

The problem is that fixing the wrong part is just a waste of time. Increasing hosting capacity won't help much if the cause is an unindexed query. Conversely, tweaking SQL won't solve the problem if the largest time is spent calling an external API.

A safer approach is to track the request journey from end to end. Think of it like sending a package: we need to know if the delay occurs when the package departs, is processed in the warehouse, or is delivered to the destination.

Start from User Experience, Not Developer Assumptions

Users don't care whether the delay occurs in PHP or MySQL. They only see a page that hasn't loaded, buttons that don't respond immediately, or a checkout process that feels stuck.

Therefore, first measure what users experience. The browser provides important information through the Network panel in Developer Tools. Pay attention to the following parts:

  • Request start: when the browser starts sending the request.
  • Waiting or TTFB: how long it takes for the server to send the first byte.
  • Content download: how long it takes to download the response.
  • Response size: whether the server sends much more data than necessary.

If the Waiting time is very long, the problem is likely on the server, application, database, or external service. If the server is fast but the page still feels heavy, check JavaScript, images, and rendering processes in the browser.

Measurements like this are more useful than the phrase β€œthe server feels slow.” Web performance should be viewed from the real user experience, not just from the time a specific function finishes on the developer's computer.

Add Timestamps in Your PHP Application

The next step is to break down the process on the server side. Don't just log that a page takes two seconds. Log which parts are using those two seconds.

A simple example:

<?php
$startedAt = microtime(true);

$beforeDb = microtime(true);
$orders = getOrders($userId);
$dbTime = microtime(true) - $beforeDb;

$beforeApi = microtime(true);
$shipping = getShippingStatus($orders);
$apiTime = microtime(true) - $beforeApi;

$totalTime = microtime(true) - $startedAt;

error_log(json_encode([
    'request' => $_SERVER['REQUEST_URI'] ?? '',
    'db_ms' => round($dbTime * 1000, 2),
    'api_ms' => round($apiTime * 1000, 2),
    'total_ms' => round($totalTime * 1000, 2)
]));
?>

The error_log() function can send messages to the system log or a configured file. For production, logging should not display sensitive data such as passwords, tokens, or full customer address details.

Logs should also contain information that aids in searching, such as URL, HTTP method, request ID, and processing time. Don't log everything blindly because overly cluttered logs can complicate investigations and may fill up server storage.

Check if the Application is Doing Too Much Work

Many slow applications are not due to one very bad operation, but rather because of too many small operations. For example, an order list page retrieves 50 orders and then runs customer queries one by one for each row.

This pattern is often referred to as N+1 query. Visually, the code looks simple, but the number of queries can increase with the amount of data.

// Potentially generates many queries
foreach ($orders as $order) {
    $customer = findCustomer($order['customer_id']);
    renderOrder($order, $customer);
}

The solution could be a single query with a JOIN, retrieving customer data in one batch, or using eager loading mechanisms if the framework supports it.

However, don't change the code based on assumptions. First, log the number of queries and their times. A good fix is one that can be compared before and after.

Use EXPLAIN Before Adding Indexes

Database indexes can indeed speed up searches, but adding indexes randomly is not a good strategy. Indexes also require space and can add overhead when data is written or updated.

Use EXPLAIN to see how MySQL plans to execute a query.

EXPLAIN
SELECT id, customer_id, status, created_at
FROM orders
WHERE customer_id = 42
  AND status = 'paid'
ORDER BY created_at DESC
LIMIT 20;

Check whether MySQL is using relevant indexes, how many rows it estimates will be read, and whether the sorting process is expensive. In MySQL that supports it, EXPLAIN ANALYZE can help compare the optimizer's estimates with the actual time and number of rows that occurred.

Composite indexes may be more suitable than two separate indexes, but the order must still follow the filtering and sorting patterns that are frequently used. This is not a rule that can be applied without looking at actual queries and data distribution.

Don't Forget About APIs and External Services

If the application calls payment, shipping, email, or AI services in the main request flow, delays from those services will also be felt by users. Even if your server and database are fast, a slow API can make the page wait.

Log the duration of each external call, response status, and the number of retries. Set reasonable timeout limits. Without timeouts, a non-responsive service can hold up the PHP worker for too long.

For processes that don't need to complete before the page displays, consider asynchronous patterns. For example, after an order is saved, sending a confirmation email can be queued to be processed in the background. Users don't need to wait for processes that are not directly related to the page display.

What Does This Mean for Us?

Performance is not a race to eliminate milliseconds from a single function. What matters more is finding the parts that most affect user experience and business risk.

Start with critical flows: login, search, checkout, dashboard, or the most frequently used API endpoints. Measure total time, break it down into several stages, and then fix the largest bottleneck. After that, measure again with comparable data.

Checklist to Do Now

  1. Open the Network panel and check if the delay occurs before or after the server sends a response.
  2. Add timestamp logging at critical points: before queries, after queries, before APIs, and before responses are sent.
  3. Count the number of queries in a single request and look for N+1 patterns.
  4. Run EXPLAIN on slow queries before changing indexes.
  5. Add timeouts and logging for each external service.
  6. Compare results before and after fixes using the same data.

In this way, performance debugging shifts from guessing to an investigative process. You don't need to immediately change hosting or rewrite the application. Often, a single accurate measurement is enough to show which part actually needs improvement.

Sources & Further Reading

– Rio Yotto @rioyotto