How to Fix a Slow WordPress Admin (wp-admin and Dashboard Taking Forever)
The front end is fine but wp-admin crawls. Find the real cause: Heartbeat and admin-ajax, update checks, WP-Cron, Action Scheduler backlogs or heavy list screens.
Many slow sites are slow by design. Find the LCP element in PageSpeed Insights, then fix the hero image, trim font files, tame sliders and animations, and stop layout shift.
Your site feels slow, PageSpeed Insights shows red scores, or Google Search Console reports “Poor” Core Web Vitals. Your host says the server is responding quickly. The slowness is coming from the page itself.
Not every slow site is the server’s fault. Some of the biggest slowdowns are design decisions: a hero photo several megabytes in size, eight font files, a slider loading five full-size images, a background video, or scroll animations that hide content until JavaScript runs. Design problems have design fixes, and this guide shows how to find and apply them.
Google’s Core Web Vitals are three measurements of real visitors’ experience. Google’s published thresholds for a “good” rating are:
Each is judged at the 75th percentile of real page visits, so most visitors, including those on slower phones, need a good experience.
<img> example shows what to look for in the Elements panel of developer tools. <link rel="preload"> lines belong in the page’s <head>: use your builder’s or theme’s setting for custom head code, or a header code plugin. CSS blocks go in your builder’s global custom CSS or your theme’s custom CSS.In the PageSpeed Insights report, look in the diagnostics for the Largest Contentful Paint element (newer versions show it under an LCP breakdown insight). It names the exact element, usually a hero image, a background image or a large heading, and splits the time into phases. A long “load delay” means the browser discovered the image late. A long “load duration” means the file is too big.
If the LCP element is an image, it is usually the single biggest win.
Check the image’s displayed width in developer tools (hover over it in the Elements panel) and compare it with the file’s real width. A 6000-pixel camera photo shown at 1400 pixels wastes most of its bytes. Export at about the displayed width, or up to twice that for high-density screens, and no larger.
WebP is supported by all current browsers and is typically much smaller than JPEG at similar quality. AVIF is often smaller still. WordPress has supported AVIF uploads since version 6.5, provided your server’s image library supports it. An image optimization plugin can convert existing uploads.
When you insert an image from the media library as a normal image, WordPress adds srcset and sizes attributes automatically, listing several sizes so phones download a smaller file. CSS background images get none of this. They also cannot be discovered until the CSS has loaded, which adds delay. For a hero, prefer a real image element positioned behind the content over a background image.
Lazy loading (loading="lazy") delays images until they are about to scroll into view. That is right for images further down, but on the hero it makes the browser wait. Check the hero’s HTML in developer tools:
<img src="hero-1600.webp" srcset="..." sizes="100vw"
width="1600" height="900" alt="..."
fetchpriority="high">
This is an example of good markup to compare against, not code to paste; the file name and sizes are made up. It should have no loading="lazy", and ideally fetchpriority="high", which tells the browser to download it first. WordPress adds this automatically to the image it judges most likely to be the LCP element (since version 6.3), but page builders, sliders and lazy loading plugins can override it. Most lazy loading plugins and builders have a setting to exclude the first images or specific classes.
If the hero must stay a CSS background, preload it in the page head so the browser finds it early:
<link rel="preload" as="image" href="/wp-content/uploads/hero-1600.webp" fetchpriority="high">
Replace the href value with the address of your own hero image: copy it from the Network tab (filter by Img) or from the File URL field in the media library. Add it only to the page that uses that image, or every page downloads it.
Every font family, weight and style is a separate file. A design using three families in four weights each, plus italics, can easily request a dozen files before any text settles. Open the Network tab, filter by Font, reload and count.
<link rel="preload" href="/fonts/brand-sans-latin.woff2" as="font" type="font/woff2" crossorigin>
Replace the href value with the address of your own font file, copied from the Network tab with the Font filter on. Add one line per font file, for one or two files at most. Keep as="font", type="font/woff2" and crossorigin as they are. The crossorigin attribute is required for font preloads even on your own domain, otherwise the browser downloads the font twice. Make sure each @font-face rule includes font-display: swap, so text appears in a fallback font immediately instead of staying invisible.
Icon fonts deserve a look too. Loading a complete icon library to show five icons costs a large file and a render delay. Inline SVG icons are lighter.
poster image, and consider showing only the poster on phones.When you do animate, animate only transform and opacity. The browser can handle those without recalculating the layout. Animating width, height, top, left or margin forces layout work on every frame and causes stutter on phones. And respect visitors who ask their operating system for less motion:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Paste this block as shown into your site-wide custom CSS; there is nothing to change. It only takes effect for visitors who have turned on reduced motion in their device settings.
Content that jumps as the page loads is measured by CLS. The usual design causes:
width and height attributes (WordPress does for media library images) or a CSS aspect-ratio, so the browser reserves the space before the file arrives.size-adjust descriptor in @font-face can fine-tune it.Chat widgets, tag managers, heatmaps, social feeds, ad scripts and multiple analytics tools each add JavaScript that competes with your page, and they are a common cause of poor INP. In PageSpeed Insights, check the third-party section to see what each one costs. Remove anything nobody looks at. For the rest, load chat widgets and video embeds only when a visitor clicks (a static placeholder that loads the real thing on click), and avoid running two analytics tools that do the same job.
After each change, purge your caches and rerun PageSpeed Insights. Lab scores vary a little between runs, so compare a few runs rather than one. Field data in PageSpeed Insights and Search Console uses a rolling 28-day window, so expect real-user numbers to improve gradually over the following weeks.
If PageSpeed Insights shows a slow server response time (the time before the first byte arrives), the bottleneck is on the server: slow plugins, missing page caching, an overloaded plan or slow database queries. Ask your host to look at it, and send them the URL, the PageSpeed Insights report, and the times you saw the slowness.
Did this fix it?
Still stuck? Start again from what you can see in the Emergency Room.
Still stuck?
Print a free one-page checklist to keep, or open the Emergency Room if the symptom does not match.
Get the free checklistsKeep reading
Search the field manual
Or jump straight to a symptom
Press / to search from any page, Esc to close