Title: EffortLess Backup And Restore
Author: domclic
Published: <strong>September 15, 2026</strong>
Last modified: September 15, 2026

---

Search plugins

![](https://ps.w.org/effortless-backup-and-restore/assets/banner-772x250.jpg?rev
=3696715)

![](https://ps.w.org/effortless-backup-and-restore/assets/icon-256x256.jpg?rev=3696715)

# EffortLess Backup And Restore

 By [domclic](https://profiles.wordpress.org/domclic/)

[Download](https://downloads.wordpress.org/plugin/effortless-backup-and-restore.1.0.25.zip)

 * [Details](https://wordpress.org/plugins/effortless-backup-and-restore/#description)
 * [Reviews](https://wordpress.org/plugins/effortless-backup-and-restore/#reviews)
 *  [Installation](https://wordpress.org/plugins/effortless-backup-and-restore/#installation)
 * [Development](https://wordpress.org/plugins/effortless-backup-and-restore/#developers)

 [Support](https://wordpress.org/support/plugin/effortless-backup-and-restore/)

## Description

A straightforward backup and restore plugin:

 * One backup automatically every day, taken through WordPress’s own scheduler (
   WP-Cron), with a fallback check on admin page loads so a low-traffic site doesn’t
   silently miss a day.
 * An “Instant Backup” button on the plugin’s Backups page for an on-demand backup
   at any time.
 * Every backup — automatic or instant — is kept for 7 days, then automatically 
   deleted to save disk space.
 * Restoring a backup replaces the current database and `wp-content` files with 
   that backup’s contents. A safety backup of the current state is taken automatically
   immediately before any restore.
 * Each backup can also be downloaded (database dump and files archive separately)
   for an offline copy.
 * No shell access or external service required — the database dump is generated
   entirely in PHP, and files are archived with PHP’s own zip extension.
 * On WordPress Multisite, one backup and restore covers the entire network at once(
   see the Multisite FAQ entry below) — managed from Network Admin, Super Admin 
   only.

### External services

This plugin does not call any external service. Every backup is generated and stored
entirely on your own server.

## Installation

**Single site:**

 1. Upload the plugin folder to `/wp-content/plugins/`
 2. Activate the plugin through the “Plugins” menu in WordPress
 3. Go to the new **Backups** menu item in the admin sidebar
 4. Click **Backup Now** to take your first backup immediately, or simply wait — one
    is taken automatically within 24 hours
 5. Under **Settings** on the same page, automatic daily backups are on by default;
    untick the checkbox and save if you only want manual, on-demand backups

**Multisite:**

 1. Upload the plugin folder to `/wp-content/plugins/`
 2. From the Network Admin’s **Plugins** page, **Network Activate** the plugin — do
    not activate it on an individual site (see the Multisite FAQ entry below for why)
 3. Go to the new **Backups** menu item under **Network Admin**
 4. The rest is identical to the single-site steps above — one backup, one restore,
    covering every site on the network at once

## FAQ

### Where are my backups stored?

Directly inside `wp-content/`, in a folder with a randomly generated name, protected
by a `.htaccess` rule that denies all direct web access on servers that honor it.
Backups are never linked to directly from the admin page — downloading one always
goes through a password-protected (nonce and login) handler.

### What exactly gets backed up?

The entire database (every table, not just WordPress’s own — any custom tables from
other plugins are included), and the entire `wp-content` directory (themes, plugins,
uploads, and anything else placed there), excluding this plugin’s own backup storage
folder.

The database is dumped table by table, not as a single all-or-nothing snapshot —
on a very active site, a write landing in one table right as its neighbor was already
dumped (for example, a new post saved between the `wp_posts` and `wp_postmeta` tables
being dumped) could in principle leave a backup with the two very slightly out of
step. This is normal for a lightweight, dependency-free backup tool and not something
to worry about on an ordinary site.

### What happens when I restore a backup?

The files backup is extracted back over `wp-content`, overwriting the current files,
and the database dump is replayed, replacing every table’s structure and data with
what was captured at backup time. This is a significant, hard-to-partially-undo 
action — a fresh backup of your site’s current state is taken automatically right
before a restore begins (unless the most recent backup is only a few minutes old
already, in which case that one serves the same purpose), so you can restore back
to “just before this restore” if needed. If that safety backup itself can’t be taken(
for example, the disk is full), the restore is aborted before touching anything,
rather than proceeding with no way back.

Only one backup or restore can run at a time — the Backups page shows a notice and
disables “Backup Now” and “Restore” while one is in progress, and automatically 
re-enables them (refreshing the page) once it finishes.

A restore runs in the background in small steps rather than one single request, 
so it can complete even on a host that limits how long a request may run — the Backups
page shows its progress and updates on its own when it finishes; there is no need
to keep a browser tab open or stay logged in for it to continue. It isn’t wrapped
in one all-or-nothing database transaction (structural changes like `CREATE TABLE`
commit immediately in MySQL regardless of any transaction). While a restore is running,
the site’s public pages (and REST API) show a brief “back shortly” message instead
of staying live — this prevents a visitor’s activity (an order, a comment, a form)
from being silently lost when the restore replaces the database moments later. If
the backup file being restored turns out to be truncated or corrupted, the restore
stops with a clear error instead of silently skipping the missing part.

### If I restore a backup, does it remove files that didn’t exist when the backup was taken?

No. Restoring extracts the backup’s files archive back over `wp-content`, which 
overwrites any file the backup contains and adds back any file it deleted — but 
a file created _after_ the backup (for example, a new plugin installed since then)
is left in place, since it simply isn’t part of what’s being restored. The database
is fully replaced either way, so a plugin added after the backup point would show
as installed on disk but not activated in the (restored) database.

### Can I use this to move my site to a new server?

The files archive and database dump can both be downloaded from the Backups page.
Restoring on a different WordPress install isn’t a built-in one-click feature in
this version — this plugin is built for keeping (and restoring) a site’s own recent
history, not general-purpose site migration.

### Does this work on Multisite?

Yes, and it always covers the whole network at once — a Multisite network’s sites
all share one database (so the database dump already includes every site’s tables,
not just one) and one `wp-content` directory, so there is no meaningful way to back
up or restore “just one site” separately from the rest.

Because of that, this plugin must be **Network Activated**, never activated on an
individual site. Network Activating moves its admin page to Network Admin  Backups,
and requires a Super Admin (`manage_network_options`) rather than an ordinary site
Administrator — restoring here overwrites every site on the network, which a single
site’s own Administrator must never be able to trigger. If it’s ever activated on
just one site by mistake, a notice on that site explains this and points you to 
Network Activate it properly instead; it doesn’t do anything from that per-site 
activation.

### I configured everything and no backups are appearing. What should I check?

WordPress’s scheduler (WP-Cron) only runs when a page on your site is visited, so
a very low-traffic site can take a little over a day for its first automatic backup
to appear — click **Backup Now** in the meantime for an immediate one. Also confirm
your host has the PHP zip extension enabled; without it, the Backups page shows 
a notice and the files portion of any backup will fail.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“EffortLess Backup And Restore” is open source software. The following people have
contributed to this plugin.

Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

[Translate “EffortLess Backup And Restore” into your language.](https://translate.wordpress.org/projects/wp-plugins/effortless-backup-and-restore)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/effortless-backup-and-restore/),
check out the [SVN repository](https://plugins.svn.wordpress.org/effortless-backup-and-restore/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/effortless-backup-and-restore/)
by [RSS](https://plugins.trac.wordpress.org/log/effortless-backup-and-restore/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.0.25

 * Internal: cleared the two remaining coding-standard warnings in the codebase (
   both about how WordPress hook names are invoked — one is this plugin’s own hook
   name held in a variable, the other is a WordPress core hook this plugin correctly
   participates in rather than owning). No behavior change.

#### 1.0.24

 * Fix: hardened the database backup format against a table or column with an unusual
   name (containing a backtick character) — such a name is now correctly escaped
   everywhere it’s written into the backup file, instead of potentially producing
   an invalid or corrupted database dump.

#### 1.0.23

 * Fix: the files archive’s entries did not mark themselves as using UTF-8 filenames,
   which the ZIP format otherwise assumes means an old, limited text encoding from
   the 1980s. This plugin’s own restore process was not affected, but a backup downloaded
   and opened with some other, stricter unzip tools could show non-English filenames(
   Chinese, Japanese, accented European names, etc.) as garbled text instead of 
   extracting them correctly. Every file the plugin now archives is explicitly marked
   as UTF-8, matching how modern ZIP tools already work.

#### 1.0.22

 * Enhancement: the “in progress” message on the Backups page and the notice shown
   when you try to start something while another operation is already running now
   say exactly what’s happening — “a backup”, “a restore”, or, when you click Restore
   and a fresh safety backup is taken first, “a backup, to be followed automatically
   by a restore” — instead of the vaguer “a backup or restore” used for every case
   before.

#### 1.0.21

 * Fix: found the actual, root cause of the long-running “Permission denied” failure
   while backing up files, thanks to a clearer error message the previous release’s
   rewrite happened to surface. It was never a problem writing the backup archive
   at all — it was one single file inside another installed plugin’s own bundled
   dependencies that this site’s server would not let the backup process read. That
   one unreadable file is now skipped, with a note in the Activity Log identifying
   it, instead of stopping the whole backup.

#### 1.0.20

 * Fix: on the same host as the previous release’s fix, the “Permission denied” 
   failure while writing the files archive turned out to follow the write location
   it was moved to as well — even a folder completely outside the site’s own files,
   on the very first archive ever created there. That rules out the security-scanner
   theory the previous fix was based on and points instead at something in how the
   server’s ZIP-writing software finishes an archive on that particular host’s storage,
   which isn’t something a plugin can work around from the outside. The files archive
   is now built with its own dedicated, self-contained code instead of relying on
   that ZIP-writing software at all, using the same simple, reliable read/write 
   approach that has never had a problem writing the database part of a backup on
   any host, including this one.

#### 1.0.19

 * Fix: identified the actual cause of the recurring “Permission denied” failure
   on one host, from real diagnostic data rather than a further guess — every standard
   check (ownership, permissions, free disk space) came back completely normal, 
   yet only the files archive specifically was ever affected; the database part 
   of the same backup, right next to it, never failed once. That pattern points 
   to something inspecting archive files in particular, most likely a security scanner
   watching the site’s own folder, and the fix is to no longer build the archive
   there in the first place: it’s now assembled in the server’s general temporary
   storage (outside the site’s own folder entirely on most hosts) and only moved
   into its final, permanent location once it’s completely finished.

#### 1.0.18

 * Enhancement: for the file-writing error that has recurred on one particular host
   across several previous releases despite retrying — that host’s exact cause still
   isn’t confirmed, and continuing to guess at fixes without more information isn’t
   productive. The Activity Log now records the concrete facts needed to diagnose
   it for good if it happens again: the affected file and folder’s permissions and
   ownership, whether they’re actually writable, how much disk space is free, and
   the server’s PHP details — no code behavior changes otherwise.

#### 1.0.17

 * Fix: on the same host that had been hitting the transient file-permission error,
   the retry added in 1.0.15/1.0.16 gave up on the first occurrence specifically
   at the finishing step, instead of getting the fair retry it was meant to. The
   whole writing step is now retried as one unit rather than only part of it, so
   it can actually recover from this the way it was designed to.

#### 1.0.16

 * Fix: the retry added in 1.0.15 for a transient file-permission error could itself
   crash a backup outright with a fatal PHP error, on PHP 8. Reusing the same internal
   zip object across a failed-then-retried attempt is not safe on PHP 8 — reported
   and confirmed from a live site. Fixed by using a completely fresh attempt each
   time instead of reusing one that already failed.

#### 1.0.15

 * Fix: reported from a live site — a backup could fail immediately with “Could 
   not finish writing the files backup archive”, even though the earlier steps that
   just ran had already written to disk without any problem, which pointed away 
   from disk space despite that being the message shown. The site’s own server log
   showed the real cause: “Permission denied” on a file that had just been created
   moments earlier in the same request — the signature of a security scanner briefly
   locking a new file to inspect it, common on shared hosting. Writing to the backup
   archive is now retried a few times before giving up, and every failure message
   now includes the exact underlying error instead of a guess, so the real cause
   is visible without needing separate access to the server’s own error log.

#### 1.0.14

 * Feature: the site’s front end (and REST API) now shows a plain “back shortly”
   message for the duration of a restore, instead of staying live. A restore replaces
   the database and files while running, sometimes across several minutes on a slower
   host — without this, a visitor could place an order, leave a comment, or load
   a half-updated page during that window, and any such activity would simply be
   lost the moment the restore finishes. This does not apply to backups, which never
   touch the live site’s content and continue to run with the site fully accessible.

#### 1.0.13

 * Fix: backups and restores now run in resumable pieces, so they complete on hosts
   that cap how long a single request may run. Previously a large backup simply 
   could not finish on such a host — confirmed on a live site whose limit was 60
   seconds, with the setting that would normally raise it disabled by the host, 
   so no amount of scheduling could have helped. Each piece now saves its exact 
   position and the next one continues from there, for as many pieces as it takes.
 * Fix: a restore could previously be left half-applied and unable to continue, 
   in two separate ways — it could stop at a moment when WordPress itself could 
   not start (so nothing was left running that could resume it), and it logged out
   the browser whose page was driving it forward. Restores now only ever pause at
   points where the site still works, and can be carried to completion by the page
   that started them even after being logged out.
 * Fix: a failure while writing a backup (a full disk, most commonly) is now detected
   and reported instead of producing a truncated archive that was listed as a usable
   backup.
 * Fix: the plugin’s own working state (whether a backup is running, and how far
   along) is now kept in a file rather than in the database, so a restore — which
   replaces the entire database — can no longer corrupt or erase the record of itself
   while running. This also fixes a successful restore sometimes reporting itself
   as partially failed.
 * Fix: the Activity Log section always appears on the Backups page now, showing“
   nothing logged yet” until there is something to show, instead of being invisible
   until the first backup ran.
 * Enhancement: progress is now reported in much finer detail — per database table
   and row count, and per batch of files — both on the page and in the Activity 
   Log.
 * Note: a restore no longer overwrites this plugin’s own files. The installed version
   is kept, since replacing the code that is running the restore part-way through
   is unsafe.

#### 1.0.12

 * Fix: reported from a live site — a backup’s database and files could finish writing
   to disk (visible via FTP) while the Backups page kept showing “running” indefinitely,
   with the backup never appearing as available. This happens when the server itself
   cuts off a backup or restore partway through finishing up, which previously wasn’t
   detected until an internal 2-hour safety valve. Backups and restores now report
   their progress in much smaller steps (per database table, per batch of files,
   per batch of SQL statements during a restore), so an interruption like this is
   now detected within a few minutes instead, and is reported as a clear error —
   including in the Activity Log — instead of just leaving the page stuck.
 * Enhancement: the busy notice now shows real progress within each stage (e.g. “
   Dumping database — table 12 of 40”, “Compressing files… (300 so far)”), not just
   which stage it’s on.

#### 1.0.11

 * Fix: the 1.0.10 Activity Log section didn’t appear on the Backups page at all
   until at least one backup or restore had run since upgrading — it now always 
   appears, showing a plain “nothing logged yet” message until then, so it’s clear
   the feature is there rather than looking like it never shipped.

#### 1.0.10

 * Feature: an Activity Log now appears on the Backups page, showing exactly what
   this plugin has done — when a backup or restore started, each stage it reached,
   and the full error message if one failed. This is visible right on the page even
   on hosts where the server’s own PHP error log isn’t accessible to the site owner.
 * Feature: the busy notice now shows what stage a running backup or restore is 
   currently at (e.g. “Dumping database…”, “Compressing files…”), instead of just“
   running”, so a genuinely stalled step is visible rather than looking identical
   to normal progress.
 * Fix: the safety net that automatically clears a stuck status after a PHP fatal
   error was being registered in the wrong request (the one that starts a backup/
   restore, not the one that actually runs it) ever since backups/restores started
   running in the background in 1.0.7 — so it never actually caught anything. It’s
   now registered in the request that does the real work, in both the normal background
   path and the 1.0.9 fallback path, and a caught fatal error is now also written
   to the new Activity Log with its full message.

#### 1.0.9

 * Fix: on some hosting setups, the request WordPress uses to start a backup/restore
   running in the background never actually reaches the site at all (a firewall 
   or CDN blocking the site from calling itself, or a security setting some hosts
   apply) — this behaves identically for every WordPress plugin that relies on WP-
   Cron, not something specific to how this plugin schedules it, and previously 
   left the busy status stuck indefinitely on hosts affected by it. The Backups 
   page now detects this after a short, fair wait and runs the operation directly
   as a guaranteed fallback, so a backup/restore always completes regardless of 
   whether that background request is able to reach the site.

#### 1.0.8

 * Fix: 1.0.7’s background dispatch could still leave the Backups page showing “
   running” for several minutes with nothing actually happening on some hosting 
   setups. The request that starts the background job now also retries automatically
   every few seconds while the busy status is showing, so a dropped first attempt
   corrects itself quickly instead of waiting on unrelated site traffic. (See 1.0.9
   for the fuller fix — this release narrowed the problem but didn’t fully solve
   it for every host.)

#### 1.0.7

 * Fix: clicking “Backup Now” or “Restore” ran the entire backup/restore inside 
   that very click’s own request — long enough on a real site to exceed a host’s
   own request time limit, which could surface as the click itself failing outright(
   for example, an Apache 503 “Service Unavailable”) well before the operation could
   finish. Backups and restores (including the automatic safety backup taken before
   a restore) now start in the background instead: the click returns immediately,
   and the Backups page updates on its own once the operation finishes. Replaces
   1.0.6’s manual “Clear stuck status” button, which is no longer needed.

#### 1.0.6

 * Fix: on some hosts, a large backup or restore could be killed outright by a server-
   side wall-clock time limit (rather than by PHP itself), which skipped this plugin’s
   own cleanup and left the Backups page showing “a backup or restore is currently
   running” indefinitely, with no error, until an internal 2-hour safety valve finally
   cleared it. A PHP-level fatal error (for example, running out of memory) is now
   also caught and cleared immediately via a shutdown handler, and the Backups page
   now offers a manual “Clear stuck status” action after 10 minutes for the cases
   a server-side kill can still cause, so an admin never has to wait out the full
   2 hours.

#### 1.0.5

 * Fix: the Backups page could trigger a PHP “Array to string conversion” warning(
   visible in the server error log) while a backup or restore was running. The busy
   indicator added in 1.0.4 passed its status value straight into WordPress’s `disabled()`—
   which is only meant to receive true/false — instead of the plain yes/no it actually
   needed. Reported from a live site; reproduced and confirmed fixed with the exact
   same warning text and line number before shipping.

#### 1.0.4

 * Feature: a running backup or restore is now shown on the Backups page (with a
   busy indicator), and “Backup Now”/”Restore” are disabled until it finishes — 
   and a second backup or restore can no longer be started while one is already 
   running, including the daily automatic backup overlapping a manual one.
 * Fix: if the automatic safety backup taken right before a restore fails, the restore
   is now aborted instead of proceeding without it — proceeding would have silently
   removed the one undo path this plugin provides.
 * Fix: the database dump’s table name and row queries now use `$wpdb->prepare()`‘
   s identifier placeholder instead of manual escaping.
 * Fix: a truncated or corrupted backup file is now detected and reported during
   restore instead of silently skipping its unfinished final statement.
 * Fix: a backup that fails partway through (after writing its database dump or 
   files archive, but before finishing) no longer leaves orphaned files behind indefinitely—
   they’re now cleaned up automatically.
 * Fix: the low-traffic-site missed-backup check is now correctly shared network-
   wide on Multisite, matching this plugin’s other shared settings.
 * Hardening: the Download and Delete links are now bound to the specific backup
   they act on.

#### 1.0.3

 * Fix: two `set_time_limit()` calls (in the backup and restore engines) now also
   suppress PHP_CodeSniffer’s `Squiz.PHP.DiscouragedFunctions` warning, alongside
   the WordPress-specific codes already suppressed there.
 * Reviewed and documented a WordPress.org Plugin Check warning (`UnescapedDBParameter`)
   on the restore engine’s SQL-replay query: replaying a complete, previously-generated
   backup statement isn’t expressible through `$wpdb->prepare()` or `esc_sql()` 
   without corrupting the restored data, so this is an accepted, justified finding
   rather than a bug — see the code comment at the call site for the full reasoning.

#### 1.0.2

 * Fix: the “missed automatic backup” self-heal check (for low-traffic sites where
   WordPress’s own scheduler might not fire on time) was hooked to fire on every
   single admin request, not just when actually viewing this plugin’s own Backups
   page. In practice this meant clicking “Backup Now” created an extra, unwanted“
   Automatic” backup alongside the instant one every time (since `admin-post.php`,
   which is what “Backup Now” submits to, itself also triggers this same check before
   running your action) — and two of those could appear at once right after first
   activation if two admin requests landed close together before the throttle kicked
   in. It now only ever runs when the Backups page itself is loaded.

#### 1.0.1

 * Renamed from “EffortLess Backup & Restore” to “EffortLess Backup And Restore”(
   matching the elbar prefix more clearly).
 * Feature: full Multisite support. Network Activate the plugin and manage it from
   Network Admin  Backups — one backup and one restore now covers the entire network(
   every site’s database tables, since they all share one database, and the whole
   shared wp-content directory) in a single operation. Restricted to Super Admins(
   manage_network_options); a per-site Administrator can no longer access it, and
   activating it on an individual site (instead of network-wide) shows a notice 
   instead of any functional menu. The backup storage location no longer depends
   on which site’s context happens to be active when it’s resolved, closing a possible
   inconsistency on networks with per-site upload paths.

#### 1.0.0

 * Initial release: automatic daily backups with a 7-day rolling retention, an instant
   on-demand backup button, one-click restore (with an automatic safety backup taken
   first), and per-backup database/files downloads.

## Meta

 *  Version **1.0.25**
 *  Last updated **1 day ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [backup](https://wordpress.org/plugins/tags/backup/)[database](https://wordpress.org/plugins/tags/database/)
   [migration](https://wordpress.org/plugins/tags/migration/)[multisite](https://wordpress.org/plugins/tags/multisite/)
   [restore](https://wordpress.org/plugins/tags/restore/)
 *  [Advanced View](https://wordpress.org/plugins/effortless-backup-and-restore/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/effortless-backup-and-restore/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/effortless-backup-and-restore/reviews/)

## Contributors

 *   [ domclic ](https://profiles.wordpress.org/domclic/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/effortless-backup-and-restore/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://id7.dev/donate/)