Skip to content

Diagnose a slow or erroring site

Goal: go from a symptom (“the site is slow”, “users are seeing errors”, “the nightly job didn’t run”) to the log or metric that explains it.

  • The symptom narrowed to a layer (edge cache, PHP, database, infrastructure) with evidence from the right log or metric.
  • A concrete next action: a query to fix, code to profile, a purge, a rollback, or a support ticket.

Jump to the symptom you have: slow site (step 1), visible errors (step 2), a job that didn’t run (step 3), or suspected resource pressure (step 4).

  1. Work from the outside in:

    Is it even reaching PHP? A well-cached site serves most anonymous traffic from Varnish. If pages that should be cached show X-Cache: MISS, you have a cacheability problem, not a performance problem; fix that first (see fix stale content, the same header-reading applies).

    Is PHP slow, or starved? Open the Drupal request log and look at two fields per request:

    [03/Feb/2026:00:14:36 +0000] www.example.com GET /pricing
    http_code=200 query= uid=0 php_pid=30961 php_time=4.203 queue_wait=0 ...
    • High php_time, low queue_wait: the request itself is expensive. Something in code, queries, or external calls is slow; continue below.
    • Low php_time, high queue_wait: requests are healthy but waiting for a free PHP process. The site is under-provisioned or being hammered; check traffic in the Apache access log and resource use in Stack Metrics (step 4).

    If requests are expensive, suspect the database next. Download the MySQL slow-query log (acli api:environments:log-download; it’s generated on demand and covers since the last daily rotation). Entries are standard MySQL slow-log format:

    # Time: 2026-07-03T02:11:07
    # User@Host: mysite[mysite] @ localhost []
    # Query_time: 4.882 Lock_time: 0.001 Rows_sent: 12 Rows_examined: 2847391
    SELECT ... FROM node_field_data n INNER JOIN ...

    The ratio that matters is Rows_examined to Rows_sent: this query scanned 2.8 million rows to return 12, which means a missing index or a query (often a Drupal View) that needs restructuring. For logs with many entries, pt-query-digest aggregates them by fingerprint; for a single suspect, EXPLAIN it over drush sql-cli.

    If the database is fine, profile the application. That’s what an APM is for: Acquia subscriptions include New Relic APM Pro (claim it per Claiming your New Relic account on docs.acquia.com), which breaks request time down by function, query, and external call. Common culprits the platform’s own guidance names: complex Views queries, calls to slow external services without timeouts, and oversized result sets processed in PHP.

    • HTTP 500s: open the PHP error log first; application errors land there with a stack trace. If it’s empty for the time window, check the Apache error log for infrastructure-level failures. A request that outlives PHP’s max_execution_time (300 seconds by default, tunable per environment; see per-environment settings) is killed and returns a 500; the fix is moving the work to a scheduled job, not raising the limit.
    • Errors you can’t reproduce: find one failing request in the Apache access log, grab its request_id, and follow that ID across the Drupal request and error logs to see exactly what that request did.
    • White screens / partial pages: PHP error log again (fatal errors), then Drupal watchdog (drupal-watchdog.log, needs the syslog module) for application-level reports.
    • It’s happening right now: stream instead of downloading, acli app:log:tail myapp.prod, or the interface’s Logs page with the error logs selected. See tail logs.
    1. Check the job’s own output: scheduled-job STDOUT is captured in cronjob.log (download from Logs). No entry at the expected time means the job didn’t fire (check its schedule and environment, see scheduled jobs); an entry with errors means it fired and failed.
    2. If the job is Drupal cron, also check watchdog: cron logs its runs there.
    3. Jobs that run over SSH but silently do nothing often point at the wrong environment or docroot; re-run the command manually over SSH and read the output directly.
  2. Check resource pressure with Stack Metrics

    Section titled “Check resource pressure with Stack Metrics”

    acli api:environments:stack-metrics-data-find returns an environment’s stack metrics as data, taking a metrics filter and a start time. The Cloud UI graphs the same CPU, memory, and storage over time (last hour to last 6 months); see Using Stack Metrics on docs.acquia.com. Two reading rules from the platform’s own docs:

    • Graphs show averages over the window, so short spikes are smoothed away; sustained elevation is what matters.
    • On Cloud Next, resources scale dynamically and load-balancer metrics reflect shared infrastructure, so low CPU on an idle site is normal. If auto-scaling isn’t keeping up, open a support ticket.

    Use Stack Metrics to answer “is the box the problem”, and the logs above to answer “what is my application doing to it”. For continuous, code-level visibility, New Relic (step 1) is the deeper tool.

The errors started with a deploy

stop diagnosing and roll back first: Roll back a release in the code-workflow guide is the runbook.

The logs don’t explain it

infrastructure-side problems (shared load balancers, platform maintenance) aren’t visible in your logs; that’s when to open a support ticket with the request_id of an affected request.

Was this page helpful?