Skip to content

How to schedule automatic WordPress backups

A backup schedule can live at your host, in a backup plugin or in a cron job on the server. Whichever you use, it has to copy the database and the files, send them off the server, and be restored once to a staging copy as proof.

By
WP Ministry
Published

In short

  • A full backup is the database and the files, made around the same time.
  • The schedule can live at the host, in a backup plugin or in a cron job on the server.
  • A plugin's schedule runs on WP-Cron, which only wakes when someone loads a page. On a quiet site it runs late.
  • A real cron job that calls wp-cron.php, with DISABLE_WP_CRON set, puts that schedule on a clock.
  • Send every backup somewhere other than the site's server, and decide how many to keep.
  • A backup is proven only by restoring it to a staging copy.

An automatic backup needs three things: something that copies the site on a schedule, somewhere off the server to send each copy, and a rule for deleting old ones. The schedule can live in one of three places: your host's own backup system, a backup plugin, or a cron job on the server that runs WP-CLI.

Whichever you choose, each backup has to hold both the database and the files, and you have to restore one to a private copy of the site. Until a backup has been restored, you do not know that it works.

What a full backup holds

WordPress's documentation splits a site into two parts and says you need both to restore it.

  • The database. Every post, page and comment, and the other data the site generates, such as the orders on a store. It lives in MySQL or MariaDB, outside the site's folder, so copying the folder does not copy it.
  • The files. WordPress itself, the themes, the plugins, your uploads, wp-config.php and .htaccess.

Treat the two as one set, made around the same time. The documentation's order is database then files when backing up, and files then database when restoring.

How often, and how many to keep

The gap between two backups is the most work you can lose. WordPress suggests once a week for a small site with few posts and daily for a busy one. The database changes with every comment and order. The files change only when you upload, update or edit something, so the database is the part to back up more often.

Kind of siteDatabaseFiles
Pages that change a few times a monthWeeklyWeekly
New posts or comments on most daysDailyDaily or weekly
A store, a membership site, or forms that keep entriesSeveral times a dayDaily

For how many to keep, WordPress's guidance is at least three to five recent backups, with copies in different places. A longer history helps when a problem is found late: damage noticed after three weeks needs a backup older than three weeks. Two weeks of daily backups is a sensible floor.

Where the schedule can live

PlaceWhat runs itWhat you needWeak point
The host's backupsThe host's own systemsA plan that includes themYou may not set the schedule, and the copies sit with the same company as the site
A backup pluginWordPress, through WP-CronA storage account outside the serverRuns late on a quiet site, and not at all when WordPress cannot run
A cron job with WP-CLIThe server's clockSSH access and WP-CLIYou write it and watch it yourself

Start with the host. Add a plugin or a cron job for whatever the host leaves out.

The host's backups

WordPress's documentation notes that most hosts back up the whole server, and that asking them for a copy of your site takes time. Find out what yours does before you add anything. WordPress backup plugins compared lists what to ask: where the copies are stored, how often they are taken, how long each is kept, whether they hold both parts, and whether you can restore and download one yourself.

If the answers are daily, away from the site's server, kept for weeks and restorable by you, that may be the whole schedule you need. Add two things. Download a copy once a month and keep it elsewhere, so that not everything depends on one company. And restore one to a staging copy, as described below.

A backup plugin's schedule

A plugin builds the backup inside WordPress and sends it to storage you choose. The comparison linked above covers which plugin offers which schedule and which storage. The setup has the same outline in each.

  1. Step 1: Set the schedule

    Use the table above. Some plugins take one schedule for the database and another for the files: UpdraftPlus has a setting for each on its Settings tab. BackWPup sets a frequency on each backup job.

  2. Step 2: Send each backup to storage outside the server

    Connect the plugin to a storage account that is not on the site's server. A backup left only in a folder on that server is lost along with it. A backup holds the whole database, user accounts and customer details included, so give that account a strong password and two-step login.

  3. Step 3: Set how many to keep

    Look for the retention setting. UpdraftPlus, for one, takes a maximum number of backups to keep, separately for the files and the database, and deletes the oldest when the number is reached. On a daily schedule, 14 keeps two weeks.

  4. Step 4: Run one now and find it in the storage

    Start a backup by hand from the plugin's screen. Then open the storage account itself and look for files with today's date. Look again after the first scheduled run.

Why a plugin's schedule can run late

WordPress has its own scheduler, WP-Cron. It does not run on a clock. On every page load it checks a list of scheduled tasks and runs the ones that are due. If a backup is set for 2:00 and nobody loads a page until 5:00, the backup starts at 5:00.

UpdraftPlus's and BackWPup's documentation both say their scheduled backups run through this scheduler. UpdraftPlus's adds what else stops it: maintenance mode, a password on the whole site at the server, and a host that blocks the site's requests to itself.

Two places show whether scheduled tasks are running on your site:

  • Site Health. Go to Tools, then Site Health. A notice that reads "A scheduled event is late" or "A scheduled event has failed" means tasks are not running when they should. "Your site could not complete a loopback request" means WordPress cannot make the request to itself that starts them.
  • WP-CLI. wp cron test tries to start WP-Cron over HTTP. When that works, it prints "Success: WP-Cron spawning is working as expected."

Put WP-Cron on a real clock

The fix in WordPress's Plugin Handbook is to have the server's scheduler, cron, call wp-cron.php at a fixed interval, and then to stop WordPress checking on every page load. You need SSH access, or a screen for cron jobs in your hosting control panel.

  1. Step 1: Open your list of cron jobs

    This opens your user's crontab, the list of commands cron runs for you, in a text editor. crontab -l prints the list without editing it.

    bash
    crontab -e
  2. Step 2: Add a line that calls WordPress every 15 minutes

    Use your own domain. The five fields before the command are minute, hour, day of the month, month and day of the week. An asterisk means every value, and */15 in the first field means every 15 minutes. -q keeps wget silent and --delete-after throws away the page it downloads. Save and close the editor.

    text
    */15 * * * * wget -q --delete-after https://example.com/wp-cron.php
  3. Step 3: Switch off the check on page loads

    Add this line above the line that says "That's all, stop editing!". From now on only the cron job starts scheduled tasks.

    wp-config.php
    define( 'DISABLE_WP_CRON', true );
  4. Step 4: Check that tasks still run

    Wait half an hour, then list what is scheduled. The table shows each task's hook and when it runs next. A task whose time passed long ago means the cron job is not reaching WordPress: take the line out of wp-config.php until you have found out why. wp cron test cannot help here, because it reports an error as soon as it finds the constant.

    bash
    wp cron event list

To undo it, remove the line from wp-config.php first, then remove the line from the crontab.

If requests to wp-cron.php are blocked

WP-CLI can run the due tasks with no web request, so a password or a firewall in front of the site does not get in the way. Use this line in place of the wget line. Change both paths to yours: command -v wp prints the first, and the second is the folder that holds wp-config.php.

text
*/15 * * * * /usr/local/bin/wp cron event run --due-now --path=/home/example/public_html --quiet

A cron job that makes the backup itself

With SSH access and WP-CLI, the server can make the backup with no plugin and no WP-Cron. wp db export writes the database to a file, using the database name and password already in wp-config.php, and tar packs the files.

  1. Step 1: Find the path to WP-CLI

    Cron starts commands with /bin/sh and a few settings of its own, not with the setup of your login. A command that works when you type it may not be found there, so the script names WP-CLI by its full path. This prints it.

    bash
    command -v wp
  2. Step 2: Save the script

    Save this in your home folder. Set WP to the path from the last step and SITE to the folder that holds wp-config.php. The backups go to a folder in your home folder and not in the site's folder, where anyone could download them.

    wp-backup.sh
    #!/bin/sh
    set -eu
    
    WP=/usr/local/bin/wp
    SITE="$HOME/public_html"
    DEST="$HOME/backups"
    STAMP=$(date +%Y-%m-%d-%H%M)
    
    mkdir -p "$DEST"
    "$WP" db export "$DEST/$STAMP-database.sql" --path="$SITE" --quiet
    gzip "$DEST/$STAMP-database.sql"
    tar -czf "$DEST/$STAMP-files.tar.gz" -C "$SITE" .
    find "$DEST" -type f -name '*.gz' -mtime +13 -delete
  3. Step 3: Run it once by hand

    The script prints nothing when it works. The listing should show two new files named with today's date and the time, one ending in -database.sql.gz and one in -files.tar.gz, each of a believable size.

    bash
    sh ~/wp-backup.sh
    ls -lh ~/backups
  4. Step 4: Schedule it

    Run crontab -e and add these lines. The second runs the script at 2:30 every night by the server's clock, which may not be in your time zone. Cron mails whatever a job prints, and this script prints only when something goes wrong. Whether that mail leaves the server depends on the host.

    text
    MAILTO=you@example.com
    30 2 * * * sh $HOME/wp-backup.sh
  5. Step 5: Send the copies off the server

    Add this as the last line of the script, with the address of a machine or storage service you can reach over SSH with a key. It copies the contents of the backups folder there.

    wp-backup.sh
    rsync -a "$DEST/" backups@backup.example.com:wordpress/

What to know about the script:

  • It stops at the first command that fails. set -e does that, so nothing old is deleted on a night when the new backup was not made.
  • It keeps two weeks on the server. The find line deletes archives that are 14 days old or older. Each run writes a full copy of the site, so check that the account has room for 14.
  • The far side keeps everything. rsync does not delete files at the destination unless told to. Set a rule for old backups there too.
  • Keep the date format in the script. In a crontab line, cron turns a % into a line break unless it has a backslash in front.

A store needs the database more often than nightly. Put the wp db export and gzip lines in a second script and schedule it with 0 * * * *, which is every hour on the hour.

To undo all of this, remove the lines from the crontab and delete the script.

Prove that a backup restores

Do not test by restoring over the live site. A restore replaces everything added since the backup was taken. Restore to a private copy, which how to set up a WordPress staging site covers making.

For a plugin's backup, use the plugin's restore screen on that copy. For a host's, ask whether a backup can be restored to a staging copy and not over the live site. For the archives the script above makes, the steps are these.

  1. Step 1: Make an empty staging site

    Create a subdomain with its own folder and a new, empty database, as the staging guide describes.

  2. Step 2: Unpack the files into it

    Use the name of the archive you are testing and the staging folder.

    bash
    tar -xzf ~/backups/2026-10-07-0230-files.tar.gz -C ~/staging.example.com
  3. Step 3: Point the copy at the staging database

    Change the database name, user and password in the copy's wp-config.php, as the staging guide shows. Then check from inside the staging folder. This must print the staging database's name, not the live one.

    bash
    cd ~/staging.example.com
    wp config get DB_NAME
  4. Step 4: Import the database

    Still in the staging folder. The first line unpacks the export and keeps the compressed file. WP-CLI answers "Success: Imported from" and the file's name. Delete the unpacked .sql file afterwards.

    bash
    gzip -dk ~/backups/2026-10-07-0230-database.sql.gz
    wp db import ~/backups/2026-10-07-0230-database.sql
  5. Step 5: Finish the copy and look at it

    Follow the rest of the staging guide: change the address in the database, and keep the copy private and unable to send email or take payments. Then log in, open a post from the past few days and an image from the media library, and on a store look for a recent order. Note how long the restore took.

Repeat the restore monthly, with the other checks in the WordPress maintenance checklist.

What not to rely on

  • A copy that exists only on the site's server. It is lost with the server.
  • A schedule nobody looks at. A schedule can stop without saying so, and no mail from cron can mean the job never ran. Read the date of the newest backup in the storage every week. WordPress's documentation also recommends a backup made by hand once in a while.
  • Last night's backup before an update. Take a fresh one first, as how to safely update WordPress describes.

If you would rather not run this yourself, our WordPress backup service takes a daily backup as part of a care plan, stores it offsite and keeps it for 30 or 90 days depending on the plan.

Common questions

My site gets few visitors. Will scheduled backups still run?

They run late, not never. WP-Cron keeps a due task in its queue and runs it at the next page load. On a site that goes a day without a visit, a daily backup can slip by a day. A cron job that calls wp-cron.php every 15 minutes, as described above, removes the wait.

Can I schedule backups without SSH access?

Yes. A host's backups and a backup plugin need no SSH. For the cron job that calls wp-cron.php, look for a cron jobs screen in your hosting control panel, or ask the host to add the line for you.

What time should backups run?

At the hour when the site is quietest. A backup made by a plugin or a cron job is built by your own server, so it competes with visitors for the server while it runs.

More on this subject

Would you rather we looked after it?

The Essential plan is $39 a month. Updates, backups, monitoring and security scanning. No edit time. It starts with a free diagnosis.