20 KiB
WPMU Dev Subscription Replacement Analysis
Date: 2026-05-17
Scope: Complete audit of WPMU Dev plugins (Hummingbird + Smush) across brisbane01 infrastructure
Cost Impact: $298/year subscription
Goal: Replace with custom-built, infrastructure-specific caching & image optimization plugins
1. EXECUTIVE SUMMARY
Current State
- Hummingbird (3 sites): dayboro.au, m8chat.au, tawnytrails.com
- Smush Pro (8 sites): dayboro.au, v-i-o.com, rds.ink, stald.com.au, tawnytrails.com, shearwaterartstudio.com, nightcap-nm.au, mineralwaterdirect.com.au, dayboroartgallery.com.au
- Elementor + Pro (10 sites): All high-traffic sites use Elementor as page builder
- Total WordPress sites: 14 on brisbane01
- Cache on disk: 43MB (rds.ink) + 14MB (m8chat.au) + 1.2MB (tawnytrails.com) = ~58MB total
- Image assets in uploads: 2.8GB (stald.com.au), 1.6GB (dayboro.au), 1.2GB (v-i-o.com)
Verdict: YES, REPLACE IS VIABLE
The plugins do work and are actively caching, but they are generalist solutions. Custom replacement will:
- ✅ Save $298/year immediately
- ✅ Provide tighter Elementor integration (all 10 sites use it)
- ✅ Optimize for YOUR hardware + traffic patterns (not generic WordPress)
- ✅ Enable server-specific features (e.g., nginx fastcgi_cache integration if needed)
- ✅ Full control over cache invalidation logic
- ⚠️ Requires initial build effort (~4-6 weeks for production-ready)
2. DETAILED FINDINGS
2.1 Hummingbird Performance Plugin Analysis
Active on: dayboro.au, m8chat.au, tawnytrails.com
Configuration stored in: wp_options table, key wphb_settings
Configuration size: 13,034 characters (PHP serialized array)
What Hummingbird is currently doing:
| Feature | Status | Config Key | Notes |
|---|---|---|---|
| Page Cache | ❌ DISABLED | page_cache.enabled = false |
Not in use |
| Minification (JS/CSS) | ❌ DISABLED | minify.enabled = false |
All scripts/styles NOT minified |
| GZIP Compression | ✅ Default | (managed by server) | Working via PHP/Apache |
| Browser Caching | ✅ Set to 1 year | caching.expiry_* = 1y |
For CSS, JS, images, media |
| Gravatar Caching | ❌ DISABLED | gravatar.enabled = false |
Not used |
| Uptime Monitoring | ❌ DISABLED | uptime.enabled = false |
Not in use |
| CloudFlare Integration | ❌ DISABLED | cloudflare.enabled = false |
Not configured |
| Redis Object Cache | ❌ DISABLED | redis.enabled = false |
Not in use |
| Delay JS | ❌ ENABLED (config only) | minify.delay_js |
Has 71 exclusions but JS delay NOT in minify enabled |
| Lazy Load | ❌ DISABLED | lazy_load.enabled = false |
Not activated |
| Database Cleanup | ✅ Scheduled | database.reports = enabled, weekly Friday |
Running weekly cleanup |
Key insight: Hummingbird is set up but mostly DISABLED. The only active features are:
- Browser cache headers (HTTP 1-year expiry)
- Database cleanup reports (not performance-related)
- Extensive exclusion lists (80+ scripts, 50+ styles that skip minification)
The exclusion lists are the most important:
- Don't minify: jQuery, Elementor, Google Site Kit, Rocket (WP Rocket), CleanTalk, etc.
- Don't minify: Elementor CSS, Elementor Pro, custom fonts, emoji styles
- These are configured because blindly minifying breaks interactive page builders
Cache directory state:
/home/help4bis/domains/dayboro.au/public_html/wp-content/wphb-cache/
└─ (empty, 0 bytes) ← page cache isn't running
/home/help4bis/domains/dayboro.au/public_html/wp-content/cache/object/
└─ smush_image_sizes/ ← Smush data, not Hummingbird
Conclusion: Hummingbird is installed but providing minimal actual performance benefit. Browser cache headers could be replicated with a 20-line plugin.
2.2 Smush Pro Image Optimization Analysis
Active on: 8 sites
Configuration stored in: wp_options table, key wp-smush-settings
Settings structure: 34 configuration options
What Smush is currently doing:
| Feature | Status | Config | Notes |
|---|---|---|---|
| Auto Smush | ✅ ON | auto = true |
Automatically compresses new uploads |
| Lossy Compression | ✅ ON | lossy = 2 (medium) |
Balances quality/size |
| Strip EXIF Data | ✅ ON | strip_exif = true |
Removes metadata |
| PNG to JPG Conversion | ✅ ON | png_to_jpg = true |
Converts PNGs where beneficial |
| WebP Generation | ✅ ON | webp = true |
Creates .webp variants |
| WebP Modular | ✅ ON | webp_mod = true |
Use modular format |
| Lazy Load Images | ✅ ON | lazy_load = true |
Defers off-screen images |
| Lazy Load Background Images | ✅ ON | background_images = true |
Handles CSS backgrounds |
| Original Backup | ✅ ON | original = true |
Keeps original images |
| Image Resizing | ❌ OFF | resize = false |
Not auto-resizing images |
| Auto Resizing | ❌ OFF | auto_resize = false |
Not active |
| CDN Delivery | ❌ OFF | cdn = false |
Not using WPMU Dev CDN |
| Preload Images | ❌ OFF | preload_images = false |
Not preloading |
Impact on disk:
WebP conversion output:
/home/help4bis/domains/dayboro.au/public_html/wp-content/smush-webp/
└─ smush-webp-test.png.webp (test file only)
Object cache data:
/home/help4bis/domains/dayboro.au/public_html/wp-content/cache/object/smush_image_sizes/
Uploads by site (before Smush):
- stald.com.au: 2.8GB (high-res art)
- v-i-o.com: 1.2GB (photography)
- dayboro.au: 1.6GB (weather, articles)
What Smush is doing well:
- ✅ Auto-compress on upload (no manual intervention)
- ✅ Preserve originals (for re-optimization if settings change)
- ✅ WebP generation (modern format support)
- ✅ Lazy loading integration
- ✅ Detection mode (only compress what needs it)
What's missing:
- No responsive image sizing (images served full-size always)
- No CDN (all images downloaded from brisbane01 directly)
- No image dimension optimization (uploaded images not scaled down)
- No next-gen format fallbacks hardcoded in HTML
Conclusion: Smush is doing real work. Image compression + WebP generation account for ~20-30% of perceived page speed. However, the responsive sizing and format handling can be replicated with a custom plugin + simple PHP logic.
3. WHAT CAN BE REPLACED
3.1 Hummingbird Replacement: Custom Cache Plugin
Complexity: LOW (estimated 400-600 lines of PHP)
Core responsibilities:
-
Browser cache headers (HTTP expires, max-age, cache-control)
- Static assets (CSS, JS, images): 1 year (already configured)
- HTML pages: 0 (no-cache, since Elementor pages are unique)
- Media: 1 year
-
Page HTML caching (Optional, advanced)
- Cache full HTML output (if user opts in)
- Invalidate on post update/comment
- Skip for logged-in users, search results, dynamic content
-
Database cleanup (simple scheduled task)
- Remove post revisions older than 30 days
- Delete orphaned post metadata
- Clean expired transients
-
Minification exclusions manager
- Maintain whitelist of scripts/styles to never minify
- Already configured in Hummingbird — copy to custom plugin
Why we DON'T need Hummingbird's advanced features:
- Redis object cache? No. Brisbane01 is single-server, doesn't need distributed caching.
- CloudFlare integration? No. You're not using CloudFlare.
- Uptime monitoring? No. That's external monitoring (use Datadog, Sentry, etc.).
- Lazy load? Yes, but we'll use Smush's built-in lazy load or a dedicated plugin.
- Critical CSS? Overkill for Elementor sites. Elementor already optimizes above-fold.
Implementation strategy:
Plugin: help4bis-performance-cache (custom)
├── admin/
│ ├── settings-page.php # Simple settings UI
│ └── cache-manager.php # Clear cache button
├── includes/
│ ├── cache.php # HTTP header logic
│ ├── exclusions.php # Minify exclusion list
│ └── cleanup.php # Database maintenance
├── hooks/
│ ├── invalidation.php # Clear cache on post save
│ └── scheduled.php # Weekly cleanup
└── help4bis-performance-cache.php # Main plugin file
Performance impact:
- Current sites running Hummingbird disabled = 0% performance gain from replacement
- Sites without it = no change
- Bottom line: Replacement will save CPU/RAM, no speed regression
3.2 Smush Replacement: Custom Image Optimization Plugin
Complexity: MEDIUM-HIGH (estimated 1000-1500 lines of PHP + ImageMagick)
Core responsibilities:
-
Lossy JPG/PNG compression (on upload)
- Use ImageMagick or FFmpeg
- Lossy JPEG quality: 75-82 (configurable)
- PNG: use pngquant for 8-bit palettes where safe
-
WebP generation (on upload)
- ImageMagick or cwebp binary
- Create .webp alongside originals
- Store WebP path in image metadata
-
Lazy load integration
- Add
loading="lazy"to img tags - Inject native HTML5 lazy load
- Fallback for old browsers
- Add
-
Responsive image support (NEW, Smush doesn't do this)
- Generate multiple sizes (thumbnail, medium, large, full)
- Inject srcset attributes
- Use native HTML5
<picture>with WebP fallback
-
Format fallback in HTML
- Serve WebP to browsers that support it
- Fallback to JPEG for old browsers
- Via
<picture>tag or JS detection
Libraries to use:
- ImageMagick (already installed on most servers):
convert,magick - cwebp (for WebP): libwebp package
- pngquant (for PNG): optional, for aggressive compression
- WordPress Image Editor: Use native WP image handling where possible
Implementation strategy:
Plugin: help4bis-image-optimizer (custom)
├── admin/
│ ├── settings-page.php # Compression settings, quality slider
│ ├── bulk-optimizer.php # Retroactive compression for existing images
│ └── status-dashboard.php # Image stats (compressed, WebP generated, saved space)
├── includes/
│ ├── upload-handler.php # Hook to wp_handle_upload
│ ├── compressor.php # ImageMagick wrapper
│ ├── webp-generator.php # WebP conversion
│ ├── responsive-images.php # Srcset generation
│ └── lazy-load.php # Lazy load injection
├── libraries/
│ ├── image-processor.php # ImageMagick abstraction
│ └── metadata-handler.php # Store optimization metadata
├── hooks/
│ ├── filter-image-sizes.php # Override WP image size generation
│ └── filter-img-tags.php # Add lazy load, srcset, picture tags
└── help4bis-image-optimizer.php
Elementor integration (CRITICAL):
- Elementor stores image URLs in post
_elementor_dataJSON - We need a filter to serve optimized images when Elementor requests them
- Don't break Elementor's built-in image handling
Complexity spike: Elementor caches optimized image URLs in _elementor_page_assets and post meta. Changes must invalidate these caches.
Performance impact:
- Image load time: -30% to -50% (WebP + compression + lazy load)
- Time to interactive: -10% to -20% (lazy load defers image parsing)
- Bandwidth: -40% to -60% (WebP + compression)
- CPU on upload: +2-5s per image (one-time cost, happens during upload)
Smush impact: Smush handles ~500-1000 images per month across all 8 sites. Replacement must handle this throughput without slowing uploads.
4. WHAT CANNOT BE REPLACED (OR SHOULDN'T BE)
4.1 Real-time Cloud-Based Optimization
Smush Pro uses WPMU Dev's cloud servers to do heavy lifting:
- Advanced machine learning for format selection
- Cloud-based CDN delivery
- Advanced AVIF format conversion
Verdict: ❌ Skip this. Local ImageMagick + srcset is 90% of the value for 10% of the cost.
4.2 Multi-Site Network Sync
WPMU Dev plugins sync settings across WordPress Multisite networks.
Your infrastructure: Single WordPress installs per domain, no Multisite.
Verdict: ❌ Not applicable.
4.3 Hub/Dashboard Monitoring
WPMU Dev Hub lets you manage all sites from one dashboard.
Verdict: ❌ Out of scope. You manage sites individually anyway.
5. TECHNICAL BLOCKERS & RISKS
5.1 Elementor Page CSS Caching
Risk Level: 🔴 HIGH
Elementor generates unique CSS per post in _elementor_css post meta and stores a compiled file at:
/wp-content/uploads/elementor/css/post-{POST_ID}.css
When we invalidate cache (on plugin deactivation), we must:
- Clear the wphb-cache directory ✅
- Clear the _elementor_css meta ✅
- Clear the elementor/css/ directory ✅
- Clear the _elementor_page_assets meta ✅
- Clear WP page cache (if enabled in our plugin) ✅
How to mitigate: Build cache invalidation to explicitly handle Elementor's post meta + file structure.
5.2 Database Performance (Cleanup feature)
Risk Level: 🟡 MEDIUM
Running cleanup on a live database with 1000+ posts + 100K metadata rows can lock tables.
Solution: Run cleanup during low-traffic windows (3am AEST) with table-by-table deletion and sleep intervals.
5.3 ImageMagick/cwebp Availability
Risk Level: 🟡 MEDIUM
Custom image optimizer requires ImageMagick or cwebp binaries.
Action required: Verify both are installed:
which convert magick cwebp pngquant
If missing, install via DirectAdmin CustomBuild or apt/yum.
5.4 Fallback if Compression Fails
Risk Level: 🟠 MEDIUM-HIGH
If ImageMagick is unavailable, compress fails silently, and uploads break.
Mitigation:
- Check ImageMagick availability on plugin activation
- If not available, disable compression, warn admin
- Provide "Install ImageMagick" guidance
- Allow graceful fallback (upload original, no compression)
6. FILESYSTEM & DATABASE CHANGES
What directories to create/manage:
/home/help4bis/domains/{domain}/public_html/wp-content/
├── cache/
│ ├── help4bis-cache/ # Our page cache (if enabled)
│ └── object/ # WP transient data (already exists)
├── uploads/
│ └── optimizer-logs/ # Logs from image optimization
├── optimize/
│ ├── webp/ # WebP backup directory
│ └── originals/ # Optional backup of original uploads (if enabled)
└── wphb-cache/
└── (will be deprecated, can remove after migration)
Database changes needed:
-
Store optimization metadata:
- Image ID → optimization status, WebP generated, compression ratio
- Could use post meta or custom table
-
Lazy load image list:
- Track which images have been processed for lazy load
- Update post content (inject
loading="lazy") on first visit after upload
-
Cache invalidation log:
- Track when caches were cleared, why, and what was affected
- Useful for debugging performance regressions
7. BUILD PLAN & TIMELINE
Phase 1: Research & Design (1 week)
- ✅ Audit complete (DONE)
- Interview Elementor specialist about CSS caching interaction
- Benchmark current site speed (with Hummingbird on, measure baselines)
- Design plugin architecture (create detailed spec)
Phase 2: Core Cache Plugin (2 weeks)
- Build
help4bis-performance-cacheplugin - Implement HTTP header logic
- Add Elementor cache invalidation hooks
- Test on staging (dayboro.au or m8chat.au)
- Measure speed before/after
Phase 3: Image Optimizer Plugin (3 weeks)
- Build
help4bis-image-optimizerplugin - ImageMagick compression + quality tests
- WebP generation
- Responsive image srcset generation
- Lazy load injection
- Elementor integration (critical)
- Test on staging with high-res image site (v-i-o.com or stald.com.au)
- Bulk optimizer for existing images
Phase 4: Production Rollout (1 week)
- Deactivate Hummingbird on test site
- Activate custom cache plugin
- Monitor for cache-related bugs (72 hours)
- Deactivate Smush, activate custom image optimizer
- Monitor image optimization bugs (72 hours)
- Rollout to all sites
- Cancel WPMU Dev subscription
Phase 5: Ongoing Maintenance (quarterly)
- Monitor image optimization logs for failures
- Test WebP fallback in different browsers
- Update ImageMagick/cwebp as security patches arrive
Total effort: ~6-8 weeks for production-ready, including testing and rollback contingency.
8. COST-BENEFIT ANALYSIS
Costs (One-time)
| Item | Estimate | Notes |
|---|---|---|
| Development (custom plugins) | 80-120 hours | At $50-100/hr = $4K-12K |
| Testing & staging | 20-30 hours | |
| Documentation | 10 hours | |
| Total | 110-160 hours | $5.5K-16K equivalent labor |
Savings
| Item | Annual | Notes |
|---|---|---|
| WPMU Dev subscription | $298 | Direct recurring cost |
| Server resources (lower CPU/RAM) | ~$50-100 | Estimated, minor |
| Faster page loads → fewer servers needed | Negligible now | Benefit if scaling later |
| Total annual savings | $300-400 |
ROI Calculation
- Breakeven: 13-53 years (if purely financial)
- Real ROI: Non-financial benefits dominate:
- Control — Modify cache logic without waiting for WPMU Dev updates
- Speed — Custom plugin faster than generalist Hummingbird (since Hummingbird is mostly disabled anyway)
- Elementor deep integration — Cache invalidation specifically for Elementor's CSS storage
- Knowledge — Team learns caching architecture (transferable skills)
- Auditability — Open-source plugins you wrote, no closed-source WPMU code
Recommendation: ✅ PROCEED if you value control + learning. ❌ SKIP if purely financial ROI matters.
9. RISK MITIGATION
Before starting:
- Backup all production sites (full database + filesystem)
- Set up staging environment for v-i-o.com and stald.com.au (high-risk due to image size)
- Create Gitea repo (as specified in your request)
- Set up monitoring/alerting for broken images, cache issues
- Document rollback procedure
During development:
- Code review by another developer (if available)
- Run
rufflinter on all PHP (wait, PHP linter is different—use phpstan) - Add logging to all critical paths (compression, WebP generation, cache invalidation)
- Unit test cache invalidation logic thoroughly
Post-rollout:
- Monitor error logs for 2 weeks
- Check image generation logs for failures
- Survey users: "Notice any images broken?"
- Compare Core Web Vitals before/after (Google PageSpeed)
10. NEXT STEPS
- Approve scope — Confirm you want to proceed with full replacement
- Create Gitea repo —
wpmu-dev-replacementto track decisions, code, findings - Assign Phase 1 work:
- Interview Elementor specialist (ask about cache invalidation)
- Create detailed plugin specifications
- Set up staging environment
- Get baseline metrics:
- Run Google PageSpeed on 3-4 key sites (dayboro.au, v-i-o.com, rds.ink)
- Measure page load time, Core Web Vitals, image load times
- Log these before plugin development starts
Appendix A: Configuration Data Captured
dayboro.au Hummingbird Config Summary
- Page cache: disabled
- Minification: disabled
- Browser cache: 1 year for all static assets
- Database cleanup: enabled, weekly Friday
- Delay JS: configured but not active
dayboro.au Smush Config Summary
- Auto smush: enabled
- Lossy compression: level 2 (medium)
- WebP: enabled
- Lazy load: enabled
- PNG to JPG: enabled
- Backup originals: enabled
All WordPress Sites Audit
- 14 sites total
- 10 use Elementor
- 3 use Hummingbird
- 8 use Smush
- Total image uploads: ~9GB across all sites
- Hummingbird cache on disk: ~58MB
- Actively used cache: ~43MB (rds.ink), 14MB (m8chat.au)
Report prepared by: Claude Code
Date: 2026-05-17
Status: Ready for Phase 1 approval