MailWizz is a sending engine first and an application second, which means the database does far more work than a typical CMS. Every campaign generates rows in the delivery logs, every open drops a record into the tracking tables, and every click, bounce, and unsubscribe writes somewhere too. On a dedicated server that churn is absorbed by generous memory and disk I/O. On Managed Cloud Shared Hosting, where your account shares a MariaDB instance with other users and operates under CloudLinux resource limits, the same growth pattern turns into slow admin pages, timeouts during sending, and eventually the dreaded "Error establishing a database connection" when your account trips its concurrent connection ceiling.

Because you are an unprivileged hosting user, none of the fixes here touch my.cnf, global variables, or the MariaDB service. Everything is done through phpMyAdmin (reachable from cPanel Jupiter under Databases > phpMyAdmin or DirectAdmin Evolution under Account Manager > phpMyAdmin), the MailWizz backend itself, and occasionally the File Manager. Understanding which tables misbehave and why lets you cut the noise without breaking the send pipeline.

Identifying which tables are actually bloated

Before deleting anything, find out where the weight sits. Open phpMyAdmin, select your MailWizz database from the left panel, and click the Structure tab. That view lists every table with a size column, but the sort is unreliable across versions, so run a precise query in the SQL tab instead:

SELECT table_name AS "Table",
  ROUND((data_length + index_length) / 1024 / 1024, 2) AS "Size (MB)",
  table_rows AS "Approx Rows"
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY (data_length + index_length) DESC
LIMIT 15;

On almost every MailWizz install the top offenders are predictable. The mw_delivery_server_usage_log and mw_campaign_delivery_log tables hold one row per email attempt and dominate size on any account that sends regularly. The archive variant mw_campaign_delivery_log_archive stores older attempts once the built-in archiving process moves them. Tracking is split across mw_campaign_track_open, mw_campaign_track_url, and mw_campaign_track_unsubscribe, all of which grow with engagement rather than with list size. Bounce processing populates mw_campaign_bounce_log, and feedback loop handling fills mw_campaign_complaint.

Two columns deserve extra attention in the Structure view. The Overhead value indicates dead space left behind by deleted rows in older MyISAM tables, and the Rows count tells you whether a table has millions of records that no longer serve a purpose. A delivery log with several million rows spanning campaigns you sent a year ago is pure dead weight; MailWizz only needs recent delivery data for reporting and resend logic, not the entire lifetime history.

Pruning logs safely with built-in tools first

MailWizz ships its own cleanup mechanism, and using it is far safer than hand-deleting rows, because the application knows which foreign relationships to respect. Log into the backend and open Settings > Cron. The relevant options control log retention: look for Delivery servers usage logs and set a reasonable number of days to keep (30 to 60 is generous for most senders). Under Backend > Settings > Campaigns you will also find archiving controls that move old delivery records out of the live table. These tasks run through the console command scheduler, so if your cron jobs are configured correctly the cleanup happens automatically. If you have not set those up yet, review our companion article on scheduling MailWizz cron jobs before relying on automated pruning.

When a table has already grown past the point where the cron command can process it within your account's execution limits, you may need to trim it directly. Do this carefully and always take a backup first. In phpMyAdmin, select the database, open the Export tab, choose Custom, select only the large log tables, pick gzipped compression, and save the file locally. Only then run a bounded delete so you never lock the table for long:

DELETE FROM mw_delivery_server_usage_log
WHERE date_added < NOW() - INTERVAL 60 DAY
LIMIT 5000;

Run that statement repeatedly rather than deleting millions of rows in one pass. A single unbounded DELETE on a huge table will exceed the query timeout on shared MariaDB and may leave a partial transaction that spikes your I/O usage. The LIMIT 5000 approach keeps each operation short and lets the server breathe between passes. The same pattern applies to mw_campaign_track_open and mw_campaign_track_url using their date_added columns.

Repairing broken tables and reclaiming space

Interrupted sends, a full disk quota, or an account hitting its I/O limit mid-write can corrupt a table, which surfaces as "Table is marked as crashed" or queries that silently return nothing. In phpMyAdmin, open the Structure tab, tick the checkbox next to the affected table, and choose Repair table from the With selected dropdown at the bottom. This issues a REPAIR TABLE that you are permitted to run as a normal user, unlike server-level maintenance.

After large deletions the physical file still holds the freed space until you compact it. Select the trimmed tables and choose Optimize table from the same dropdown, which rebuilds the table and rebuilds indexes:

OPTIMIZE TABLE mw_delivery_server_usage_log,
  mw_campaign_track_open,
  mw_campaign_track_url;

For InnoDB tables MariaDB reports "OK" but performs a recreate-and-analyze internally, which is exactly what reclaims the space and refreshes statistics. Watch your disk usage in cPanel under Files > Disk Usage before and after; a heavily bloated log table often frees several hundred megabytes. If an optimize fails because the temporary rebuild would exceed your quota, delete in smaller batches first, then optimize once the table is smaller.

Fixing connection errors and inefficient indexes

Connection errors during sending rarely mean the database is down. On shared hosting they almost always mean MailWizz opened more simultaneous connections than your account allows, which happens when several delivery processes and the web backend all query oversized tables at once. Reducing the number of parallel sending processes fixes this at the source. In Settings > Cron, lower the Campaigns at once and Subscribers at once values, and in each delivery server configuration under Servers > Delivery servers, cap the hourly and daily quotas so fewer workers spin up together.

Slow queries usually trace back to reporting screens scanning tracking tables without a usable index. MailWizz creates its indexes at install, but a table restored from an older backup or migrated between hosts can lose them. Confirm with the SQL tab:

SHOW INDEX FROM mw_campaign_track_open;
EXPLAIN SELECT * FROM mw_campaign_track_open
  WHERE campaign_id = 1 ORDER BY date_added DESC;

If EXPLAIN shows a full table scan with a high row estimate and no key used, the index is missing. Recreating a standard index is a permitted user operation and dramatically speeds up campaign reports:

ALTER TABLE mw_campaign_track_open
  ADD INDEX fk_campaign_id (campaign_id);

Only add indexes that mirror MailWizz's own schema; inventing custom composite indexes can conflict with future upgrades. Finally, edit your account's .user.ini in the MailWizz root through File Manager to raise max_execution_time and memory_limit modestly (for example max_execution_time = 120 and memory_limit = 256M) so maintenance queries and the cleanup cron have room to finish without tripping a PHP timeout mid-repair.