Shopware 6 Hidden Gems #17: e2e:dump-db & e2e:restore-db — the database snapshot commands hiding in APP_ENV=e2e
Fabian Blechschmidt
This one starts with a confession: I found these commands in the source, wrote half a blog post about them, ran bin/console e2e:dump-db to grab example output — command not found. Grep says it exists. The console says it doesn’t. That kind of afternoon.
The resolution turned out to be the most interesting part, so let’s do this one as a small detective story.
The commands
SystemDumpDatabaseCommand and SystemRestoreDatabaseCommand live in core/DevOps/System/Command/. Together they’re a compact snapshot/rollback pair:
bin/console system:dump # writes var/dumps/{host}_{dbname}.sql
bin/console system:restore # reads the same file back
The dump is a mysqldump wrapper with genuinely sensible choices baked in (SystemDumpDatabaseCommand.php:48-58):
-q --opt --hex-blob --no-autocommit — streaming, binary-safe, fast to restore.
The file starts with SET unique_checks=0;SET foreign_key_checks=0; — the restore doesn’t trip over foreign key ordering.
And the default --ignore-table list is the quiet highlight: enqueue, message_queue_stats, dead_message, increment, refresh_token. Someone thought about what does not belong in a snapshot — queue state, statistics counters, session-ish tokens. Restoring yesterday’s enqueue table into today’s shop is a great way to replay messages nobody wants replayed.
You can pass your own ignores with -i table1 -i table2, with the usual Symfony catch: your list replaces the default, so re-add the queue tables if you extend it.
The mystery: why isn’t it in bin/console list?
Because of where the commands are registered. Not in the regular services.xml — in services_e2e.xml. And the DevOps bundle loads that file under exactly one condition (core/DevOps/DevOps.php:27-30):
if ($environment === 'e2e') {
$loader->load('services_e2e.xml');
}
APP_ENV=e2e. Shopware has a third environment besides dev and prod, built for end-to-end test runs, and these commands are part of its toolkit: snapshot the database once, run a Cypress/Playwright suite, restore between specs. The same XML even registers alias command names that spell out the workflow — e2e:dump-db, e2e:restore-db, e2e:cleanup (three names, same two classes). Not only that, but somehow the original commands are de-registered.
Bonus discovery in the same file: in e2e mode, the usage-data gateway client is replaced with Symfony’s MockHttpClient — your test runs don’t phone home. And there’s a matching config package directory (Framework/Resources/config/packages/e2e/) that tweaks other things for test stability.
So how do you actually use it?
APP_ENV=e2e bin/console e2e:dump-db
# ... test wildly, break things ...
APP_ENV=e2e bin/console e2e:restore-db
That works on any installation — the environment just needs to boot, and e2e behaves like a stripped prod. For its intended purpose (E2E suites resetting state between runs) this is exactly what you want, and dramatically faster than re-running fixtures.
Should you use it as your general-purpose dev snapshot tool? Honestly: it’s fine for that, with two caveats. The file path is fixed (var/dumps/{host}_{dbname}.sql — a second dump overwrites the first, there is no history), and running your whole session in APP_ENV=e2e disables the dev toolbar and friends, so the two-command dance above with the env prefix is the practical pattern. If you want multiple named snapshots, the takeaway is the recipe, not the command: the mysqldump flags plus the ignore list plus the FK-checks prefix are a proven combination — steal them for your own tooling.
The meta-lesson
The reason I’m writing this one up isn’t just the two commands. It’s the pattern they revealed: Shopware registers different services per environment, and grep-driven discoveries can be booby-trapped by it. If the source says a service exists and the container disagrees, check for services_{env}.xml loading in the bundle’s build() — there’s a services_dev.xml too (it holds a test-coverage generator command). File that under „debugging techniques I learned by accident“.
TL;DR
system:dump / system:restore are a built-in mysqldump/restore pair with smart defaults (FK checks off, queue and token tables excluded) — but they only exist in APP_ENV=e2e, where they’re also aliased as e2e:dump-db / e2e:restore-db / e2e:cleanup for test-suite state resets. Run them with an env prefix, mind the fixed single-file path, and remember the broader lesson: some Shopware services only exist in certain environments.
Next up: media:delete-unused — reclaiming gigabytes of orphaned media, with the audit report and grace period the docs forgot to mention.
Did you know about the e2e environment? Drop me an email — I’m collecting who did!
Found in Shopware 6.7.0.0: commands in core/DevOps/System/Command/SystemDumpDatabaseCommand.php (default ignores at line 69, dump flags at 48-58) and SystemRestoreDatabaseCommand.php, env-conditional registration in core/DevOps/DevOps.php:27-33 and DevOps/DependencyInjection/services_e2e.xml (incl. e2e:* aliases and the MockHttpClient swap).