At five client sites you can keep everything in your head. At twenty you start forgetting which host a site is on. At fifty, a single bad plugin update, an expired card on a registrar account or a former contractor who still has an admin login can turn into several emergencies on the same morning. Most agencies only build a system after that morning.
This guide is for freelancers and small agencies looking after many WordPress sites. It is a practical operating model: one inventory, access that belongs to the right people, a standard stack, staged updates in waves, backups you have actually restored, monitoring that wakes a human, and a clean way to offboard clients and staff. Adopt it a piece at a time; even the first two steps remove most of the risk.
What goes wrong at scale
The failures are rarely clever attacks. They are ordinary gaps multiplied by the number of sites:
- Nobody can say, quickly, which sites run the plugin in today’s vulnerability alert.
- One shared “agency” admin account and password is used on every site, by everyone, for years.
- Domains and licenses renew on a card that expired, in an account only one person can open.
- “Update all” runs across every site at once, and a builder update breaks layouts on thirty of them.
- Backups exist but live on the same server, or have never been restored.
- Uptime alerts go to an inbox nobody reads.
- A staff member or contractor leaves and keeps access to everything.
Step 1: Build one inventory and keep it current
A single source of truth for every site is the foundation for everything else. A spreadsheet is fine to start; a management dashboard or a database is fine later. What matters is that it exists, is complete and is updated whenever something changes. For each site, record:
| Field |
Why you need it |
| Site address, client, plan tier, client contact |
Who to tell, and what you promised them |
| Registrar, account owner, renewal date |
Domain expiry is the outage nobody can fix quickly |
| DNS host and CDN or proxy, account owner |
Where to go when records need to change |
| Hosting company, plan, server, account owner |
Who to contact in an outage, and who pays |
| PHP and WordPress versions |
Planning upgrades and spotting sites left behind |
| Theme, builder and premium plugins, license holder, renewal |
Answering “which sites run X?” in seconds |
| For each paid product: who pays, auto-renew on or off, seats used, and which sites depend on it |
Knowing exactly what breaks if a card fails or you cancel a license |
| Backup system, where copies are stored, last test restore date |
Knowing a restore will work before you need it |
| Monitoring in place (uptime, SSL, domain, forms) |
Gaps show up as blanks |
| Email: mailbox provider and how site mail is sent |
Avoiding email breakage during DNS changes |
| Known quirks and exceptions |
“Do not update the booking plugin without testing” belongs here, not in someone’s memory |
Pay attention to the email address on each renewal. Whoever receives the renewal and password reset emails effectively controls that account, so it should be the owner’s monitored address, not a former employee or a personal inbox. Set reminders well ahead of each date (a month ahead gives time for a card update or a client decision, with a second reminder a week before), and when a renewal passes, move the date forward straight away so the list never goes stale.
For new sites, the site takeover access inventory is a good intake form, and the renewals register covers every date that can expire. Review the inventory monthly as part of your maintenance routine.
You can collect much of the technical data automatically. With WP-CLI, which runs in a terminal on the server (over SSH, in the site folder), these commands report the versions and plugins on one site:
wp core version
wp eval 'echo PHP_VERSION . PHP_EOL;'
wp plugin list --fields=name,status,version,update_version
wp theme list --fields=name,status,version
wp core version prints the WordPress version. wp eval runs one line of PHP; here it prints the PHP version WP-CLI is using, which is normally the same as the site’s, though some hosts run a different PHP for the command line. wp plugin list with --fields limits the table to the columns named; an empty update_version means no update is available. The WP-CLI cheat sheet explains more.
Step 2: Fix access before anything else
Access is where a large portfolio becomes dangerous. The goals are simple: every person has their own login, every account belongs to the right owner, and you can remove someone everywhere in an afternoon.
Clients own their accounts
Registrar, hosting, analytics, Search Console and paid licenses should belong to the client, with you added as a user, delegate or team member wherever the service supports it. Many registrars, hosts and Google services let an owner add other people with their own logins. This protects the client if you disappear, protects you from accusations if the relationship ends, and keeps you out of the situation in our guide former web designer has my domain or logins.
Named accounts, not shared ones
- Give each team member their own WordPress account on each site, with the lowest role that does the job. Not everyone needs Administrator.
- Retire the shared “agency” admin login. Shared accounts make it impossible to see who did what, and impossible to remove one person.
- Use a password manager with separate vaults or folders per client, shared only with the people who work on that client.
- Turn on two-factor authentication for every admin account and every registrar, host and DNS login. See stopping brute-force attacks for login hardening.
- Use a separate SSH key per person, so one key can be removed without affecting anyone else.
Audit who can get in
Run this regularly on each site to list administrators:
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
Anyone you do not recognize, any former staff member and any former contractor should be removed or downgraded, after checking with the client. Also check for application passwords, which let tools log in without the normal password and survive a password change:
wp user application-password list USERNAME
Replace USERNAME with the login or user ID. An empty table is good. Revoke any you cannot explain. If you find an account that should not exist, treat it as a possible compromise and follow admin account compromised: how to contain it.
Step 3: Standardize the stack
Every unique combination of plugins is another thing to test. A standard stack makes updates predictable and lets you build habits that work everywhere.
- Choose one backup method, one security approach, one SMTP or transactional email method, one SEO plugin and one form plugin for new builds, and stick to them.
- Keep a short approved plugin list with a reason for each. New plugins need a reason to join it.
- Standardize on a small number of builders or themes, chosen with handoff and exit in mind. The guide to choosing a builder or theme for client sites covers the trade-offs.
- Record every exception in the inventory, with a note on how to update it safely.
- When you take on an inherited site, bring it toward the standard stack during paid onboarding. The inherited site takeover playbook walks through it.
Step 4: Update in waves, with staging and rollback
“Update everything on every site at once” is how one bad release becomes fifty broken sites. Use waves instead.
- Triage the release. Read changelogs for builders, WooCommerce, payment gateways, security plugins and major versions. Security fixes for actively exploited issues jump the queue; see what to do about a plugin vulnerability alert.
- Wave 1: your own sites and a few low risk client sites (a “canary” group). Update, check, and wait a day or two for problems to surface.
- Wave 2: the bulk of brochure sites. Update with a backup taken first, then check key pages.
- Wave 3: shops, memberships and business critical sites. Update on staging, test checkout, forms and logins, then push to live at a quiet time, without losing new orders. See pushing staging to live without losing orders.
The safe update routine covers the per-site steps, auto-updates and rollback in detail. Whatever tool you use to update in bulk, it should let you exclude specific plugins, take a backup first and see what will change before it does.
Bulk commands with WP-CLI aliases
WP-CLI can run the same command against many sites over SSH using aliases. On your own computer, create a wp-cli.yml file (or add to ~/.wp-cli/config.yml) like this, with your real SSH users, hosts and paths:
@client-a:
ssh: deploy@client-a-host.example.com/var/www/client-a/public_html
@client-b:
ssh: deploy@client-b-host.example.com/home/clientb/public_html
@canary:
- @client-a
Each alias points to a site folder on a server where WP-CLI is installed. @canary is a group alias that runs against every site listed under it. WP-CLI also provides @all, which runs against every alias you have defined. Then, from a terminal on your own computer:
wp @all core version
wp @all plugin list --update=available --fields=name,version,update_version
wp @canary plugin update --all --dry-run
wp @canary plugin update --all --exclude=woocommerce
The first two report versions and pending updates on every site, which is ideal for answering “which sites need this patch?”. --dry-run shows what would update without changing anything. --exclude skips the plugins named (comma separated), so you can hold back risky ones for manual testing. Good output lists each site’s alias followed by its results; an SSH error for one site usually means a wrong path, a missing key or WP-CLI not installed on that server. Run your backup before any command that changes things.
Step 5: Backups you have actually restored
A backup you have never restored is a hope, not a plan. For a large portfolio:
- Keep copies off the server, and ideally independent of the host, so a hosting account problem does not take the backups with it.
- Match frequency to change. A brochure site can manage with daily; a busy shop needs its database backed up more often.
- Keep enough history to go back before a hack that started weeks ago.
- Restore test on a rotation. Each month, restore a few different sites to a staging location and check they work. Record the date in the inventory. Over a year, every site gets tested.
- Know the restore steps for each backup method, written down, so anyone on the team can do it. See restoring a WordPress site from a backup.
The backup plan checklist lists the decisions to make. If a backup plugin fails on a large site, see backup and migration plugin failures.
Step 6: Monitoring that reaches a person
Monitor the things that cause outages, and route alerts so a human sees them.
| Monitor |
Catches |
| Uptime and response checks from outside |
Site down, errors, slow responses |
| Certificate expiry |
SSL renewals that failed silently; see expired certificate errors |
| Domain expiry and status |
Renewals that failed on an expired card |
| Vulnerability alerts for your plugin and theme list |
Patches you need to apply quickly |
| Core and plugin file integrity |
Changed or injected files |
| Form and email delivery tests |
Sites that look fine but lose inquiries or orders |
For file integrity, WP-CLI compares files against the official checksums from WordPress.org:
wp core verify-checksums
wp plugin verify-checksums --all
“Success: WordPress installation verifies against checksums.” is good. Lists of files that “should not exist” or “do not verify” need investigating. Premium plugins not hosted on WordPress.org cannot be checked this way and will be reported as skipped or failed, which is expected.
Alert fatigue is a real risk. If an alert fires every day and nothing is wrong, people stop reading it. Tune thresholds, send only actionable alerts to the urgent channel, and decide who is on duty when. Our diagnostic tools are useful for one-off checks of DNS, SSL and headers when an alert does fire.
Step 7: Have an incident routine before you need it
When something breaks on several sites at once, you need a routine, not improvisation.
- Confirm the scope: one site, one server, one plugin across many sites?
- Use the inventory to list every affected site and client.
- Tell clients early and promise update times, not fix times. The site down client emails are ready to adapt.
- Log what you do as you go with the incident log, then send a short report afterward.
- For a hack, follow the hack recovery checklist and check every site that shares the same server or credentials.
Step 8: Offboard clients and staff cleanly
When a client leaves, hand over a recent backup, transfer licenses and accounts that belong to them, remove your monitoring and your access, and confirm in writing. The client offboarding template is a step by step checklist. Remove the site from your inventory, bulk update aliases and backups schedule, and keep only what your agreement allows you to retain.
When a team member or contractor leaves, work from the inventory: remove their WordPress accounts, revoke their SSH keys and application passwords, remove them from the password manager and from every registrar, host, DNS and analytics account they were added to, and rotate any shared secret they could have seen. Do it on their last day, not when you remember.
A rhythm that keeps it under control
| How often |
What |
| Daily |
Review alerts. Apply urgent security patches. |
| Weekly |
Update waves. Check pending updates across all sites. |
| Monthly |
Per-site maintenance checklist, admin audit, renewals due in the next 60 days, a few restore tests, client reports. |
| Quarterly |
Review the standard stack, PHP versions, licenses and the approved plugin list. |
| Yearly |
Review prices and plans. See how to price website care plans. |
If none of that worked
If the portfolio already feels out of control, do not try to fix everything at once. Start with the two steps that remove the most risk: build the inventory (even roughly) and fix access, especially registrar accounts and shared admin logins. Then add off-site backups and uptime monitoring. Standardizing the stack and wave updates can follow over a few months.
If one host is behind most of your incidents, gather the evidence from your inventory and incident logs (dates, durations, error messages) before raising it with them or planning a move with the switching hosts checklist. If you are about to take on a batch of sites from another agency, do the takeover audit on each before you agree a price.