Skip to main content

Drupal performance audit: caching, Core Web Vitals & load readiness

If you run a business-critical Drupal platform that has slowed down, or one with a known traffic peak ahead, a Drupal performance audit measures the whole request path: cache and render architecture, database and query cost, frontend delivery. The findings come back rated by criticality, with an effort estimate against each one.

Drupal Certified Partner: Silver

What a Drupal performance audit covers

A Drupal performance audit is a point-in-time, timeboxed review of a Drupal platform against performance criteria. It produces a rated findings list and a prioritized set of recommendations, each carrying an effort estimate. Scope spans backend and frontend in one engagement, because the two are usually measured separately and diagnosed together.

The scope lines are agreed per engagement:

  • Request path and server response: where time is spent before the first byte leaves the origin.
  • Cache and render architecture: Internal Page Cache, Dynamic Page Cache, Redis or Memcache, reverse proxy, CDN edge, BigPipe.
  • Database and query cost: expensive views and programmatic queries, oversized tables, search offloading.
  • Frontend delivery and Core Web Vitals: LCP, CLS and INP, render-blocking assets, third-party script weight.
  • Image and asset delivery: formats, responsive image styles, lazy loading, static-asset cache headers.
  • Traffic and bot load: how much of the origin's work is bogus traffic, and how much headroom is left.

Authenticated and editorial traffic is in scope alongside anonymous pages. Intranets, member areas and the back office are where page-level caching stops helping and the diagnosis has to change.

The audit is timeboxed by the agreed budget. Coverage, sample URLs and the accesses needed are fixed at scope definition rather than left open as a review of every page on the platform. Findings then arrive rated Very High, High, Medium or Informational, so remediation can be sequenced and budgeted instead of triaged from a flat list.

They've Trusted Metadrop

From manufacturing and B2B distribution to humanitarian NGOs, professional associations and public administrations, organizations operating in 50+ countries have relied on Metadrop for Drupal performance, caching and infrastructure work.

What clients say

Platform owners describe what changed once performance work was measured rather than guessed.

When a performance audit pays for itself

If one of these describes your platform, the audit is the right next step.

  • Response times have drifted and nobody can point to the change that caused it.
  • A traffic peak is on the calendar: a campaign launch, an enrolment or admissions window, a season, an election, a breaking-news cycle.
  • Search visibility is under pressure and Core Web Vitals appear in the diagnosis. Field data is a page-experience signal Google uses, and treating it as the single cause of a ranking change would overstate it.
  • The platform was inherited, taken over from a previous provider or built by people who have since left, with no documented performance baseline.
  • An agency or systems integrator needs an independent read on a platform it has taken responsibility for, before committing to a remediation budget.
  • Procurement asks for evidence: public-sector and education tenders increasingly score page performance alongside accessibility, and a rated audit is the artefact that answers them.
  • Editorial productivity is the symptom: slow save operations, slow admin views, slow previews. Back-office cost is a performance finding in its own right.

A home-appliance manufacturer's platform was taken over from a previous provider and audited across security, performance, functional and accessibility criteria. The findings scoped an urgent action plan, and a CDN and WAF deployment followed.

The cache and render layers we diagnose

The audit reads the cache and render stack as an architecture, layer by layer, and checks whether each layer is doing work the layer above it has already done.

LayerWhat it storesWho it servesHow it is invalidatedWhen enabling it is the right call
Internal Page CacheWhole rendered pages, held inside DrupalAnonymous visitors onlyCache tags or a manual clear; max-age does not applySmall and medium sites with no proxy cache in front
Dynamic Page CacheThe page response except its personalized partsAnonymous and authenticated visitorsCache tags on the stored responseAny platform carrying logged-in traffic
Redis or Memcache render cacheIndividual render arrays: blocks, fields, view resultsEvery request that has to rebuild a pageCache tags, plus backend eviction when memory fillsWhen rebuilds are frequent and the database cache backend is the limit
Reverse proxy (Varnish)Whole HTTP responses in front of Drupal, before PHP runsAnonymous visitors onlyPurge by cache tag through surrogate keys, or by URLHigh anonymous traffic that should not reach the origin
CDN edgeWhole responses and static assets, at points of presence near the visitorAnonymous visitors, in every regionPurge by surrogate key or URL, plus the cdn-cache-control max-ageGeographically spread audiences, asset-heavy sites, peak and bot absorption

Metadrop's engineers publish on Drupal's Internal Page Cache and on the state cache in Drupal 10.3, which is the same material this section is grounded in.

Internal Page Cache

Internal Page Cache

Internal Page Cache serves anonymous users only, returning a stored response with no rendering work. Two things about it surprise teams regularly. max-age does not apply: a configured max-age will not make it invalidate on its own, so invalidation comes from cache tags or a manual clear, and a custom cache tag invalidated on a schedule is the documented workaround. Cache contexts do not apply either to the pages it serves, because every anonymous visitor receives the same response.

It is best suited to small and medium sites. Where a proxy cache already sits in front of Drupal, two layers are performing the same job, and Metadrop's practice is to disable Internal Page Cache in environments that have a proxy cache configured. The audit records which layer is actually answering each sampled URL, so the recommendation rests on observed behaviour rather than on configuration screens.

Dynamic Page Cache and the X-Drupal-Dynamic-Cache header

Dynamic Page Cache caches the page response except the personalized parts, which makes it the layer that matters for logged-in traffic. Every response carries X-Drupal-Dynamic-Cache with one of three values: HIT, MISS or UNCACHEABLE.

A page going UNCACHEABLE means Drupal decided the response is poorly cacheable. Three root causes account for most of them: a max-age at or below the configured threshold, a high-cardinality cache context, or a high-invalidation-frequency cache tag. The most common avoidable cause is the user cache context applied too broadly. Where the requirement is only "different per visitor", session is narrower; where it is only "different per query parameter", url.query_args, or a single named parameter, is narrower still.

The audit samples URLs across templates and reports which pages are uncacheable and why, which is what turns a slow-site complaint into a fix list.

Redis Icon

Redis and Memcache render cache

Render-cache entries multiply as the cartesian product of a component's cache contexts. A block carrying languages:language_url, route and user on a large multilingual site can reach hundreds of thousands of stored entries, which is why the diagnosis ranks contexts by cardinality: url is very high, route and user are high, languages:language_url and timezone are low.

A handful of causes recur and all of them are fixable. Views exposed-filter blocks inherit the url context, a known Drupal core issue. Visibility conditions pull in route. Admin blocks get left enabled on the frontend theme. Server-side personalization forces user. Where the content is light enough to render per request, auto-placeholdering keeps the surrounding page cacheable instead of the block making it uncacheable.

On Memcache, the finding to watch is the object-size limit: objects above it are split and stored in parts, which carries a penalty when it happens often.

Varnish, CDN and purge coordination

The target behaviour is checked explicitly: the origin is reached only when no layer holds a valid copy, and a changed URL reaches visitors on their next request. That depends first on header hygiene, meaning a cache-control value instructing browsers to revalidate, a cdn-cache-control (or s-maxage where the layer does not support it) carrying the long edge max-age, and an etag or last-modified present so a layer can validate without asking the origin.

It also depends on purge strategy: invalidation by cache tag where the layer supports surrogate keys, by URL where it does not. The surrogate-key header name differs per provider, and getting it wrong is a silent failure, since content simply goes stale. File and asset invalidation is checked separately from pages, because files can change without their URL changing.

Three practical checks catch most real misconfiguration: whether only anonymous responses are cached, whether the outermost layer sorts query parameters so one page is not stored many times over, and whether an inner layer is leaking cdn-cache-control outward. Where the platform runs on a managed vendor stack, the vendor's own purger and its cron-driven queue are reviewed as part of the same layer.

BigPipe and placeholdering

BigPipe streams the cacheable shell of a page first and fills the personalized fragments as they are rendered, so perceived load time improves without the uncacheable parts becoming cacheable.

The audit keeps perceived performance and origin cost apart as two findings: BigPipe changes the first, placeholdering strategy changes the second. Findings name the components worth placeholdering, and the ones where placeholdering is hiding a query that should be fixed instead.

Scaling under traffic spikes

Traffic peaks, bots and load readiness

The question this section answers is how much headroom is left, not how fast the site is today.

Load and stress testing runs against an agreed profile: concurrency, ramp, the URLs and the authenticated journeys that matter. It runs on a non-production environment, and the results are read against the cache configuration rather than in isolation. Alongside it sits peak-shape modelling from real data, using previous campaign or season traffic, the cache hit ratio at the edge, and the proportion of requests that reach the origin.

Bot load is measured as part of capacity. AI-crawler and scraper traffic has grown into a real share of origin work, so a WAF plus edge rules is capacity planning as much as it is security. The failure-mode review closes the section: what happens when the origin saturates, whether stale content can still be served, and whether alerting fires before a visitor reports the problem.

Metadrop has published analysis of bot traffic's impact on websites and how to mitigate it, and of Drupal Status Report requirements as an operational health signal.

Frontend delivery, Core Web Vitals and INP

Measurement covers the three current Core Web Vitals: LCP, CLS and INP. INP replaced FID as a Core Web Vital in March 2024, so what gets measured is interaction responsiveness rather than first-input delay. Field data and lab data are read together, since real-user field measurements say what visitors experience and lab profiling says why.

INP diagnosis is specific work: long tasks blocking the main thread, event handlers doing layout work, heavy hydration or carousel libraries, and JavaScript loaded before it is needed. Around it sit the delivery findings. Render-blocking and bundling covers whether CSS and JavaScript are split by component or shipped as one monolithic bundle, what sits above the fold, and what can be deferred. Third-party script weight is inventoried with its owner, so tag managers, chat widgets, consent tools, analytics and marketing pixels each get an attributed cost. Image and asset delivery covers modern formats, responsive image styles matched to real breakpoints, lazy loading below the fold, priority hints for the LCP element, and long-lived cache headers on static assets.

No target score is promised. The deliverable is the list of what is costing time, in the order worth fixing.

An international humanitarian NGO's platform had critical CSS inlined, its LCP image preloaded with a priority hint, earlier connections opened to external resources, a legacy carousel library removed and lazy loading retuned, improving layout stability and largest-contentful-paint behaviour; images moved to a lighter format with delivery tuned for mobile.

Database, search and query cost

Expensive queries are located and attributed: views with unindexed filters, programmatic queries in preprocess or hook code, and queries running on cacheable pages that should never re-run. Table growth is treated as a performance finding too, because form submissions, node revisions, paragraph revisions and log tables reaching millions of rows change backup, migration and query cost alike.

Logging in production is reviewed as an architecture decision: database logging on a high-traffic site grows fast, and a centralized syslog-based pipeline is the sustainable pattern. Search offloading asks whether complex or faceted search still runs against the database when a dedicated search index would carry it, and whether the index itself is current and correctly sharded. Cron and queue work covers long operations that belong in batches or console processes rather than in a web request.

Observability gaps are reported as findings in their own right: without aggregated data across requests, an isolated slow page is a distraction rather than a diagnosis. Metadrop's engineers have published on extending Drupal's log system with Monolog and on reading HTTP response headers as a diagnostic, both routine parts of this layer's review.

A multinational engineering and construction group's Solr search core was upgraded to a current major version and its search migrated to a new managed provider when the previous managed offering was discontinued, keeping search performance on a supported service through the transition.

How the audit runs and what you receive

The engagement runs in four stages, the last of them optional:

  1. Scope definition agree the topics, the sample URLs, the journeys to test, and the accesses and tooling needed.
  2. Timeboxed execution run the checks against the agreed scope and capture the baseline measurements every later comparison depends on.
  3. Presentation walk the findings and the prioritized recommendations with the technical and non-technical members of the buying group, in language both can act on.
  4. Optional consultancy loop where contracted, re-measure the agreed KPIs against the audit's baseline at an agreed cadence and report progress. Every KPI tracked traces back to a check that established its baseline.

What you receive is a findings deck with each finding rated and tied to its evidence, a prioritized recommendation list carrying an effort estimate per item so remediation can be budgeted, and, where a consultancy phase follows, a recurring report against the baseline.

CriticalityWhat the rating means
Very HighA blocker; nothing lower is worth fixing first.
HighSignificant impact, fix in the same round.
MediumWorth fixing, batch it.
InformationalRecords a state or a deliberate decision; reported, never actioned.

There is deliberately no Low level: a finding that would sit there is either informational or worth batching.

The audit is a diagnosis, and the remediation is a separate decision. Fixes can run as a project, or as evolutive work inside a Drupal maintenance contract. Measurement is non-intrusive, using read-only access plus an agreed sample, and load testing runs on a non-production environment. Clients already on a maintenance contract get an automated check pass at no extra cost, monthly; a contracted audit is the in-depth, manually reviewed version of it.

Behind the engagement sit Metadrop's standing credentials: 15+ years of Drupal specialization, Drupal Silver Certified Partner status, ENS certification and a GDPR, WCAG and NIS2 compliance track record, on platforms serving 50+ countries and 30+ languages.

Infrastructure sizing and provider selection are a separate conversation, so see Drupal hosting when the finding is that the platform has outgrown its plan. Performance is also one topic in the audit family and can be combined into one engagement with accessibility, SEO, UX/UI or GEO & AEO: one scope, one presentation, one prioritized list.

Frequently asked questions about performance audits

  • Why is my Drupal site slow?

    Slowness on a Drupal site usually traces to one of four places: pages that cannot be cached, a cache layer duplicating another, queries that re-run on every request, or frontend weight in scripts and images. The distinguishing signal is who is slow. If anonymous visitors are slow too, the cause is usually cacheability or origin cost; if only logged-in users are slow, the diagnosis moves to render caching and personalization. A performance audit exists to replace that guesswork with measurement, then rank the causes by impact.

  • What is the difference between Varnish and Drupal's Internal Page Cache?

    Varnish is a reverse proxy sitting in front of Drupal, answering anonymous requests without the request reaching PHP at all. Internal Page Cache is a Drupal core module that stores rendered pages inside Drupal, also for anonymous users. Running both means two layers doing the same job, and Metadrop's practice is to disable Internal Page Cache where a proxy cache is configured, keeping it for development environments if needed. One thing to check before disabling it: Internal Page Cache is what provides the etag and last-modified headers, so those have to come from elsewhere once it is off.

  • What does X-Drupal-Dynamic-Cache: UNCACHEABLE mean?

    An X-Drupal-Dynamic-Cache: UNCACHEABLE response means Drupal judged that page too poorly cacheable to store, so it is rebuilt on every request. Three causes explain most of them: a max-age at or below the configured threshold, a high-cardinality cache context such as url or user, or a cache tag invalidated very frequently. The header is readable in any browser's network panel, which makes it the cheapest first diagnostic on a slow Drupal page.

  • How do I reduce Redis render cache entries?

    Redis render-cache entry counts fall by reducing cache-context cardinality, not by increasing memory, because entries multiply as the cartesian product of a component's contexts. Start by counting entries per cache bin and, inside the largest bin, per block, then read the contexts reported beside each one. Typical fixes are replacing a url or route context with a custom context that returns only the handful of real variants, moving block visibility logic into the theme layer, loading personalized data client-side instead of adding user, disabling admin blocks on the frontend theme, and forcing auto-placeholdering on light blocks whose contexts are unavoidable.

  • How do I fix INP on a Drupal site?

    INP on a Drupal site is fixed on the main thread: long tasks, event handlers doing layout work, and JavaScript executing before the interaction it serves. Common Drupal-specific contributors are heavy carousel and slider libraries, per-page monolithic JavaScript bundles, jQuery-era plugins kept for one component, and third-party tag-manager payloads firing on load. The usual sequence is to split JavaScript into per-component libraries, defer what is not needed for the first interaction, replace heavy widgets, then re-measure with field data rather than a single lab run.

  • Can you tell us whether the site will survive our next traffic peak?

    Traffic-peak readiness is assessed by testing against an agreed load profile: concurrency, ramp, the URLs and the authenticated journeys you expect, run on a non-production environment and read together with the cache configuration and the edge hit ratio. The output is where the platform saturates first and what to change before the date, rather than a certified capacity figure. Bot and crawler traffic is included in the profile, because a share of peak-day origin work is usually not human.

  • How long does a Drupal performance audit take, and does it touch the live site?

    A Drupal performance audit is timeboxed to the agreed budget, which is what sets its duration: a focused scope on a single site runs in days, a large multisite or multilingual estate in weeks. Measurement is non-intrusive, with read-only access and an agreed URL sample on production, while load testing and any experiment that changes configuration run on a non-production environment. What shortens the timeline most is having the accesses, the environments and the sample list ready at scope definition.

  • What does a Drupal performance audit cost?

    A Drupal performance audit is quoted per engagement, because the timebox is the product: the budget sets the depth of review, and the scope is agreed before any work starts. The cost drivers are the number of sites and languages, the number of distinct templates and journeys to sample, the size and age of the custom codebase, and whether load testing is included. Rates are not published; a scoping conversation is what produces a figure, and it is the same conversation that fixes the scope.

Ready to measure your Drupal performance?

Send the platform URL, the symptom you are seeing and any date you are working towards. The reply proposes a scope: the topics, the sample URLs and the accesses needed.
Nothing is committed at that point. The scope and the timebox are agreed before the audit starts, and the findings are yours regardless of who implements them.
Escribe tu mensaje aquí...
I have read and accepted the privacy policy regarding data processing.
Answers are generated automatically by AI and may not be accurate.