What's Specific For Shopware
- Build-time compilation. Composer install,
bin/console plugin:refresh,
bin/build-js.sh, bin/build-administration.sh,
and bin/console theme:compile all run during image
build. Deploy is an image swap, not a build.
- Per-slot external Redis for the Symfony cache pool
and HTTP cache so blue/green doesn't cold-start the storefront — true
zero-downtime deploys, with no maintenance window and no dropped cart.
- OpenSearch per tenant for product search and
category navigation — operator-managed, single-node per tenant with
rebuild-from-MySQL recovery.
- Symfony Messenger workers run as platform-managed
processes (not
php bin/console messenger:consume in
cron). They scale independently and restart cleanly on deploy.
What synware Gets You That Generic Shopware Hosting Doesn't
- Diagnostic report on every deploy. Cart page slow
after a plugin update? We trace the request through the controller,
the service decorator, and the Doctrine query — and name the line.
- Plugin-level cost attribution. Which plugin is
burning the most CPU during cart-add? Which one issues the slowest
SQL? Every span ties back to the originating service.
- Per-tenant MySQL with XtraBackup + binlog shipping.
14-day PITR window. A bad plugin migration doesn't end your week.
- Destructive-migration-aware classifier. Shopware
migrations run arbitrary PHP in
update() and
updateDestructive(); static analysis can't see the DDL
they emit. We clone, dry-run, and tell you what the migration
actually does before it touches production.
- MCP server for your agent. Cursor or Claude Code can
deploy, roll back, clear the Symfony cache pool, restart Messenger
workers, and query traces without leaving your IDE. Same tool surface
our internal team uses.
What A synware Diagnostic Looks Like
Real finding shape. Every report carries a finding ID, the evidence
trace, the exact file:line, and a recommended fix — in your stack's
idioms, not a generic dashboard widget.
Plugin subscriber issuing N+1 on product load
Evidence
trace c7f2a90: storefront → product.loaded subscriber → mysql
pattern: SELECT ... FROM custom_pricing WHERE product_id = ?
fired 312 times per page · 4.1s total Code Location
custom/plugins/AcmePricing/src/Subscriber/ProductSubscriber.php:74
foreach ($products as $p)
$this->loadPrice($p->getId()); // one query per item Recommended Fix
1. Batch into one WHERE product_id IN (...) query
2. Or add the association to the Criteria in the route
Expected p99: 4.1s → ~70ms