All WordPress HTML Templates Forms & Webhooks AI & Tools
WordPress

WordPress Maintenance Retainers: Scope, Pricing and What to Automate

A practitioner’s guide to wordpress maintenance plan pricing: real tier figures, scope that holds up, what to automate with WP-CLI, and the leaks that kill

A real working moment illustrating the theme of an article about wordpress maintenance plan pricing. Wide 16:9 banner, one strong focal point, magazine editorial quality, authentic and unstaged.

A client called on a Sunday because their checkout page was returning a white screen. A WooCommerce extension had auto-updated overnight, hit a fatal on a deprecated function, and nobody noticed for nine hours. The backup was from the host’s nightly snapshot, which meant restoring would have wiped eleven orders. We spent three hours fixing forward instead of rolling back.

That site was on a $99 per month plan. The incident cost us about four hours of senior time. Four months of margin, gone in one evening, because the scope said “updates and backups” and nothing about who owns the blast radius when an update goes wrong.

Good wordpress maintenance plan pricing isn’t about finding the number clients will accept. It’s about building a scope you can deliver profitably at volume, automating the parts that are genuinely mechanical, and pricing the parts that aren’t.

Key Takeaways

  • Price on risk and recovery time, not on a task list. A brochure site and a membership site can need identical tasks and wildly different retainers because one has a 15 minute acceptable downtime and the other has none.
  • Automate detection and verification, never remediation. Automated updates with automated visual regression and a 30 second health check are safe. Automated “fix it” scripts are how you get a half-migrated database at 2am.
  • Our floor is around $149 per month for a static-ish site and $600 or more for anything transactional. Below $100 you are selling an uptime monitor with a human-shaped wrapper, and one incident erases a year of revenue.
  • Content edits are the single biggest scope leak. Cap them in hours, not in “small requests”, and make the cap visible in the monthly report so nobody is surprised at renewal.
  • A retainer only survives if the site is maintainable. Audit plugins and remove the page builder dependency before you sign, or you are renting someone else’s technical debt at a fixed price.

Defining wordpress maintenance services scope so it holds up in month 14

Most retainer agreements fail because they list activities: “weekly plugin updates, monthly backups, security scanning, uptime monitoring.” All true, all useless when the dispute arrives. The client’s mental model is “you keep the website working,” and a list of activities doesn’t map to that.

Write scope as three separate things: what we watch, what we do on a schedule, and what we fix for free versus what gets billed.

  • Monitored: uptime (60 second interval), SSL expiry, core and plugin versions against known CVEs, PHP fatal log volume, autoloaded options size, cron health, 404 spikes on key URLs.
  • Scheduled: patch cycle (weekly or fortnightly), offsite backup verification with an actual restore test quarterly, a performance pass quarterly, PHP version review twice a year.
  • Included remediation: anything we broke, anything an update broke, anything a monitored alert catches. Capped at a stated number of hours per month.
  • Billed separately: new features, design changes, content migration, recovery from client-side errors (someone deleted a page, someone installed a plugin from a YouTube tutorial), and anything caused by third party services we don’t control.

That last category needs teeth. We write it as: “If the root cause is a change made outside our access logs, the fix is billable at our standard rate.” It’s not punitive. It’s the only thing that stops a plan turning into unlimited development.

A real working moment that fits an article section about

Three tiers, and why the middle one is the only one that matters

We run three. The bottom tier exists to say yes to small clients without losing money. The top tier exists so the middle one looks reasonable. The middle tier is the business.

Care (from $149/mo)

Brochure sites, 10 to 40 pages, no transactions. Fortnightly patch cycle, daily offsite backups with 30 day retention, uptime monitoring, 1 hour of content edits. Recovery target: site restored within 4 business hours. No weekend cover. This tier is a volume play and only works if it’s at least 80 percent automated.

Managed (from $600/mo)

Lead generation sites with real revenue attached, booking systems, light ecommerce, multilingual installs. Weekly patch cycle on staging first, 3 hours of changes, quarterly performance and accessibility pass, a named engineer, 1 hour response during business hours. Most of our agency work lands here.

Critical (from $1,500/mo)

WooCommerce over roughly 500 orders a month, membership sites, anything with a login wall and recurring billing. Staging-first everything, out of hours cover, 30 minute acknowledgement, a documented runbook per site, and a quarterly restore drill that actually gets performed with a stopwatch. If you run gated content, the dependency graph between the membership plugin, the payment gateway and your caching layer is where incidents come from, and we’ve written about why that architecture needs to come first.

Do the margin arithmetic before you publish a price. Take your target effective hourly rate, say $120. A $149 plan buys the client roughly 75 minutes of human time a month, total, including the report. Everything else has to be machine time. If your patch cycle takes 45 minutes of manual clicking per site, that tier is already unprofitable at 20 clients.

What to automate, and the line you shouldn’t cross

The rule we settled on after a few painful years: automate detection and verification, keep a human in the loop for anything that writes to production.

Automate confidently: backup execution and offsite transfer, checksum verification, version and CVE diffing, uptime and SSL checks, expired transient cleanup, visual regression snapshots, the first draft of the monthly report.

Do not automate: database migrations, plugin updates on transactional sites without a staging run, rollbacks, or anything that touches a payment gateway configuration. A rollback script that runs unattended will eventually restore a database over live orders. WordPress 6.3 added rollback for failed manual plugin updates, which helps, but it covers the install step only, not the data your plugin wrote on activation.

Here’s the shape of the patch job we run per site. It’s a WP-CLI script invoked from CI, not from the server’s own cron, so a broken site can’t break its own maintenance.

#!/usr/bin/env bash
set -euo pipefail
SITE="$1"; ALIAS="@${SITE}"

Snapshot first. Named by commit so the report can reference it.

wp "$ALIAS" db export "/backups/${SITE}-$(date +%Y%m%d-%H%M).sql" --add-drop-table

Fail loud if core files have been modified. Catches injected code

and sloppy "just edit it on the server" fixes.

wp "$ALIAS" core verify-checksums || echo "CHECKSUM DRIFT: $SITE" >> /tmp/review.log

Show what would change before changing it. Output goes in the report.

wp "$ALIAS" plugin update --all --dry-run

Only auto-apply on the allowlist. Everything else waits for staging.

while read -r plugin; do wp "$ALIAS" plugin update "$plugin" done < "/etc/patch-allowlist/${SITE}.txt"

Post-update sanity: a fatal shows up here immediately.

wp "$ALIAS" eval 'echo "ok";' curl -sf -o /dev/null -w '%{httpcode} %{timetotal}\n' "https://${SITE}/"

The allowlist file is the whole trick. Plugins that have never broken anything in 18 months go on it. The payment gateway, the membership plugin, the form handler and the SEO plugin never do, regardless of how boring their changelogs look.

On the WordPress side, lock down the auto-updates you don’t want the dashboard deciding for you. This goes in an mu-plugin, not functions.php, so a theme switch can’t disable it:

<?php
// mu-plugins/00-update-policy.php
addfilter( 'autoupdate_plugin', function ( $update, $item ) {
    // Never let WP auto-update anything that touches money or access.
    $hold = [ 'woocommerce', 'restrict-content-pro', 'gravityforms' ];
    return in_array( $item->slug, $hold, true ) ? false : $update;
}, 10, 2 );

// Minor core only. Majors get a staging pass.
addfilter( 'allowmajorautocore_updates', '__return_false' );

// Stop file edits from the dashboard entirely on managed sites.
if ( ! defined( 'DISALLOWFILEEDIT' ) ) {
    define( 'DISALLOWFILEEDIT', true );
}

Pair the patch job with visual regression. Playwright or BackstopJS against six or eight URLs per site (home, a service page, the contact form, a product, cart, checkout) catches the layout break that a 200 status code happily hides. Our threshold is 0.1 percent pixel difference before a human looks. Anything above that gets flagged, not reverted automatically.

Monitoring that produces action, not noise

Uptime pings are table stakes and tell you almost nothing. The alerts that actually earn the retainer are the slow ones.

Autoloaded options size is the best early warning in WordPress. WordPress 6.6 added a Site Health check that flags installs over 800KB of autoloaded data, which is a sensible trigger. Past that threshold, every single page load is deserializing a few hundred kilobytes before it renders a byte. Query it directly:

SELECT optionname, LENGTH(optionvalue) AS bytes
FROM wp_options
WHERE autoload = 'yes'
ORDER BY bytes DESC
LIMIT 20;

Nine times out of ten the top rows are orphaned records from a plugin somebody uninstalled two years ago. Which is the real point: most maintenance problems are install problems. Before quoting a retainer, run a proper plugin audit and price the cleanup as a separate onboarding project. We charge 6 to 12 hours for it and refuse the retainer if the client declines. A 47 plugin install with three overlapping caching layers cannot be maintained for $149 a month by anyone.

Also monitor your forms. Not the page, the submission path. A form that renders perfectly and silently drops leads is the most expensive failure in a maintenance plan because nobody notices for weeks. We run a synthetic submission weekly against a test-tagged endpoint. On static or hybrid builds that’s trivial with a hosted endpoint like WebForms. On WordPress it means a scheduled check that the mail transport still authenticates.

The scope leaks, ranked by damage

  1. Content edits with no cap. “Just swap this image” arrives 14 times a month. Give a named hour budget, track it in a shared doc, and report consumed hours every month. Clients respect a visible meter.
  2. The site nobody can maintain. Page builder sites where a core update breaks a layout nobody can repair without the builder license. If you inherit one, budget the migration to native blocks as a project, or accept that your patch cycle will always need a human.
  3. Third party integration drift. A CRM changes an API field, forms stop syncing, the client blames the website. Write into scope that you’ll diagnose for free once and bill the fix.
  4. Hosting you don’t control. If the client insists on their nephew’s reseller account with PHP 7.4 and no staging, either require a move or write an explicit exclusion. We’ve stopped taking retainers on hosting we can’t SSH into.
  5. Emergency expectations without emergency pricing. If the contract says business hours, hold the line on the first Sunday or you never will again.

Reporting, and the renewal conversation it earns

Nobody reads a 14 page PDF of green checkmarks. The report that keeps a website care plan agency relationship alive for years is one page, sent the same day each month, with four things: what changed, what we caught, hours used against hours included, and one recommendation with a price.

That last line is the whole point. “Your product images are 2.4MB each and LCP on mobile is 4.1 seconds; we can fix it in 5 hours” converts far better than any sales email, because it arrives from the people who already have the keys. Roughly a third of our project revenue originates in a maintenance report.

Keep the consolidation argument in your pocket too. Sites built on a single well-maintained foundation patch faster than sites assembled from nine unrelated plugins. That’s a large part of why we keep client work on a known base like CanvasWP where we can. Fewer moving parts, fewer Monday morning surprises.

Frequently Asked Questions

What should a WordPress maintenance plan cost in 2026?

Realistically, $149 to $300 per month for a brochure site, $500 to $900 for a business site with lead generation or light commerce, and $1,500 or more for high volume WooCommerce or membership platforms. The driver is acceptable downtime and recovery complexity, not page count. Anything under $100 a month cannot absorb a single three hour incident.

Should content edits be included in the retainer?

Include a capped number of hours, typically 1 hour on entry tiers and 3 to 5 on managed tiers. Uncapped “small edits” is the fastest route to an unprofitable plan because the definition of small belongs to the client. Report consumed hours monthly so overage is a conversation, not a shock.

Is it safe to enable WordPress auto-updates on client sites?

For minor core releases, yes, on almost every site. For plugins, only on an allowlist of components that have proven stable and that don’t touch payments, access control or forms. Pair it with a post-update HTTP check and visual regression, because a successful install and a working page are different things.

How often should you test a restore, not just take a backup?

Quarterly at minimum, and time it. An untested backup is a guess. We restore to a throwaway staging environment, run a short smoke test, and record the elapsed minutes in the client file so the recovery target in the contract is a measurement rather than a promise.

Should you take on a maintenance plan for a site you didn’t build?

Only after a paid audit. Inheriting an unknown install at a fixed monthly price means absorbing unknown risk, and bloated plugin stacks or abandoned page builders can double your patch time per cycle. Quote the cleanup separately and be willing to walk away if the client refuses it.

Where to start

Pick your lowest priced existing client and time the next patch cycle with a stopwatch. Every minute of it. If the total exceeds the human time their fee buys at your target rate, you have two choices: automate the mechanical portion this month, or reprice at renewal. Don’t do both at once, because you won’t know which one worked.

Then write your exclusions list before you write your inclusions list. The retainers that stay profitable are the ones where everyone agreed, in writing, what isn’t covered.

automating wordpress backups and health checks how much to charge for wordpress maintenance website care plan agency wordpress autoloaded options site health wordpress maintenance plan pricing wordpress maintenance retainer scope creep wordpress maintenance services scope wp-cli automated plugin update script