What is MageMonitor?
MageMonitor is a comprehensive store health monitoring extension for Magento 2. It continuously scans your server, database, cron system, cache layer, frontend, and security posture — then surfaces actionable findings directly in your Magento admin panel with exact instructions to fix each issue.
Requirements
| Component | Requirement | Notes |
|---|---|---|
| Magento | 2.4.x | Community and Commerce editions. Constraint: magento/framework ^103.0 |
| PHP | 8.1 – 8.5 | CLI binary must be accessible to www-data. Constraint: ~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5 |
| Database | MySQL 5.7+ / MariaDB 10.4+ | InnoDB engine required |
| PointOfCode_Core | Required | Shared PointOfCode module (admin menu, licence validation). Composer pulls it in automatically as pointofcode/module-core ^1.2; for a manual install, upload it to app/code/PointOfCode/Core/ alongside MageMonitor |
| Magento Cron | Must be configured | Run as www-data user, not root |
| Redis | Optional | Required for session/cache monitoring |
| Varnish | Optional | Required for Varnish hit rate monitoring |
| AWS SDK | Optional | Required only for AWS Integration feature |
| Composer | 2.x | For installation |
www-data user (not root). Running as root creates permission issues with generated files and can prevent MageMonitor from reading certain system stats. Verify with: sudo crontab -u www-data -lInstallation
Upload the Module
Extract the MageMonitor zip file and upload the MageMonitor folder to your server at app/code/PointOfCode/MageMonitor/ using SFTP or SCP. MageMonitor depends on PointOfCode_Core: if app/code/PointOfCode/Core/ is not already on the server (it is shared by every PointOfCode extension), upload it the same way.
Installing with Composer instead? composer require pointofcode/module-mage-monitor installs both modules; then continue with step 2.
scp -r MageMonitor/ user@server:/var/www/magento/app/code/PointOfCode/
Enable the Module
SSH into your server and run these commands as the web user:
sudo -u www-data php bin/magento module:enable PointOfCode_Core PointOfCode_MageMonitor
sudo -u www-data php bin/magento setup:upgrade
sudo -u www-data php bin/magento setup:di:compile
sudo -u www-data php bin/magento setup:static-content:deploy -f
sudo -u www-data php bin/magento cache:flush
sudo systemctl reload php8.2-fpm # use your PHP-FPM service name
Production mode: setup:upgrade empties pub/static, so always run setup:static-content:deploy in the same window — otherwise the Magento admin returns 500 errors while the storefront still looks fine behind full-page cache. Reloading PHP-FPM makes it drop the previously compiled code; without it the module can appear not to work. Both apply to every future update too.
Verify Installation
Check the module is active:
sudo -u www-data php bin/magento module:status PointOfCode_MageMonitor
# Expected output: Module is enabled
Enter Your License Key
In the Magento Admin go to Stores → Configuration → PointOfCode → MageMonitor → License and enter your license key. Then go to PointOfCode → MageMonitor in the admin menu to access the dashboard.
Optional: Enable Varnish Stats Access
If you use Varnish, add www-data to the varnish group for full statistics access:
sudo usermod -a -G varnish www-data
sudo systemctl restart php8.1-fpm # or php8.2-fpm
License Activation
MageMonitor uses domain-based license validation. Your license key is tied to the domain where it is installed and validated automatically on every scan.
Go to Configuration
Navigate to Stores → Configuration → PointOfCode → MageMonitor → License
Enter License Key
Paste your license key in the format POC-XXXX-XXXX-XXXX-XXXX. This key was emailed to you after purchase from store.pointofcode.com.
Save and Validate
Click Save Config. The domain is auto-detected from your Magento base URL. Validation runs automatically in the background every 30 minutes via cron.
General Settings
Master controls for the entire MageMonitor module. Navigate to Stores → Configuration → PointOfCode → MageMonitor → General Settings.
Performance Monitoring
Controls how MageMonitor tracks request performance and how frequently it scans your server and Magento health. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Performance Monitoring.
request_slowlog_timeout and the web user can read the log file./var/log/php-fpm/www-slow.logvar/log/*.log together exceed this many megabytes. This is really a statement about the disk — 500 MB is most of a small VPS partition and a rounding error on a large volume — so set it against the space you actually have.Store Intelligence
Deep background analysis that runs every 3 hours and surfaces proactive recommendations about your database, cron system, and performance configuration. All checks are strictly read-only. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Store Intelligence.
Database Thresholds
Cron Thresholds
Performance Thresholds
Cache Health Monitoring
Read-only health checks for Varnish, Redis, Magento FPC, and OPcache. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Cache Health Monitoring.
Database Monitoring
Thresholds for the database checks: which tables appear under “Database Cleanup Opportunities” on the Database tab, plus concurrent slow queries, indexer changelog backlog and url_rewrite growth. MageMonitor never deletes data — it only provides copy-paste SQL suggestions. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Database Monitoring.
*_cl) table holding more than this many undrained rows. Rows only accumulate when the indexer is not draining them, which is why product and price edits stop reaching the storefront.url_rewrite table holds more than this many rows. Store views multiply this table, so a large catalogue across several store views can legitimately hold millions of rows — raise it rather than leaving the finding permanently open.Server Load Monitoring
Thresholds for PHP-FPM worker saturation, unrecognised CPU consumers, disk headroom and Redis pressure. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Server Load Monitoring.
pm.max_children, read from your pool configuration — not against a guessed number. A server with 10 workers and one with 200 are judged on the same scale.maxmemory. Only applies when a limit is set; with no limit there is no percentage to measure against.maxclients limit. At the limit Redis refuses new connections outright, which reaches customers as error pages rather than slow ones.Search Monitoring
Thresholds for the two search findings that depend on how much search traffic a store receives. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Search Monitoring.
search_query table once it holds more than this many stale one-off terms — searched exactly once, more than 90 days ago. These rows serve no purpose and slow down search autocomplete.Security Settings
Controls for file integrity monitoring sensitivity and brute force detection thresholds. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Security Settings.
Alert General Settings
Settings that apply to all alert channels (Email, Slack, and Webhook). Navigate to Stores → Configuration → PointOfCode → MageMonitor → Alert General Settings.
[Store Monitor]. Its purpose is filing: one constant string at the front of the subject is what lets you write a single Gmail or Outlook rule that labels, archives or routes every monitoring email. Leave empty for no tag.Email Alerts
Configure email notifications for health issues, score drops, and downtime events. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Email Alerts.
Subject line format
Every alert subject opens with the severity, followed by your store name. Subjects are plain text with no emoji, so they survive strict spam filters and older mail clients — and so you can filter on them reliably.
| Situation | Subject |
|---|---|
| A critical finding | CRITICAL: Your Store — Database Overloaded (5 slow queries) |
| A high-severity finding | HIGH: Your Store — PHP-FPM Workers 92% Saturated |
| Warnings only | WARNING: Your Store — 2 issues detected |
| A known finding got worse | ESCALATED to CRITICAL: Your Store — PHP-FPM Workers 96% Saturated |
| A finding cleared, others remain | RESOLVED: Your Store — Redis Evicting Keys cleared, 2 still open |
| A finding cleared, nothing left | RESOLVED: Your Store — Redis Evicting Keys cleared, nothing open |
| Score improved since the last alert | RECOVERED: Your Store — score improved to 88/100 |
| Nothing outstanding | ALL CLEAR: Your Store — score 88/100 |
| An endpoint stopped responding | OUTAGE ALERT: Checkout — Your Store |
| A test send | [TEST] CRITICAL: Your Store — Sample: 5 Concurrent Slow DB Queries |
Tip: because the severity is the first word, you can route alerts in your mail
client without pattern-matching the whole subject — for example, send anything starting with
CRITICAL: to your phone and leave the rest in your inbox.
Your store name comes from Stores → Configuration → General → Store Information → Store Name. If that is blank, alerts fall back to "Magento Store", so it is worth setting before you enable alerting.
admin@store.com,tech@store.com. All listed addresses receive every alert — there is no per-recipient severity filtering.Slack Notifications
Receive MageMonitor alerts directly in your Slack workspace. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Slack Notifications.
Create a Slack App
Go to api.slack.com/apps, click Create New App → From Scratch, give it a name like "MageMonitor", and select your workspace.
Enable Incoming Webhooks
In your app settings, go to Incoming Webhooks, toggle it on, then click Add New Webhook to Workspace. Select the channel to post alerts to.
Copy the Webhook URL
Copy the generated webhook URL (format: https://hooks.slack.com/services/T.../B.../...) and paste it into the Slack Webhook URL field in MageMonitor configuration.
https://hooks.slack.com/services/TXXXXXXX/BXXXXXXX/XXXXXXXXX#store-alerts. Leave empty to use the channel selected when creating the webhook.Webhook Integration
Send MageMonitor health data to any HTTPS endpoint — useful for integrating with custom dashboards, PagerDuty, or other monitoring systems. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Webhook Integration.
Content-Type: application/json. MageMonitor sends a JSON payload with all current detections and store health data.X-MageMonitor-Signature HTTP header so your endpoint can verify the request authenticity. Use a random generator to create a strong secret.Uptime Monitoring
MageMonitor checks your store's uptime every 3 minutes and sends immediate alerts on downtime and recovery. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Uptime Monitoring.
https://www.store.com/checkout
https://api.store.com/healthFile Integrity Monitoring
SHA-256 hash monitoring of critical Magento files. Any unexpected change triggers a HIGH severity security alert. Navigate to Stores → Configuration → PointOfCode → MageMonitor → File Integrity Monitoring.
app/etc/config.php or .htaccess. After adding new paths, the baseline is rebuilt on the next scan.Frontend Monitoring & Headless Support
JavaScript error collection from real visitor browsers. Captured errors appear in the JS Errors tab. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Frontend Monitoring & Headless Support.
Headless / PWA stores: keep this enabled as well. It does more than inject the script — the
/magemonitor/jserror/collect endpoint checks this setting on every request and rejects the payload while it is off, so disabling it would make the standalone snippet below collect nothing. Enabling it costs nothing on a headless store, because no Magento storefront pages are rendered to your customers.This setting drives the cap on native Magento frontends only. The standalone snippet below cannot read Magento configuration, so headless stores set the same cap by editing its
_max value directly.Headless / PWA Compatibility
MageMonitor is fully compatible with headless and PWA storefronts. Almost all of its value — server health, database, cache, cron, security, uptime, CDN/WAF monitoring, Quick Fixes, and all alerts — runs entirely server-side and works identically regardless of how your storefront is built. The only feature that requires extra setup for headless stores is JS error collection.
Full Compatibility Table
| Feature | Native Magento Frontend | Headless / PWA Frontend |
|---|---|---|
| Server, Database, Cache, Cron, Security Monitoring | ✓ Full | ✓ Full |
| Quick Fixes | ✓ Full | ✓ Full |
| Uptime Monitoring | ✓ Full | ✓ Full |
| CDN / WAF Monitoring | ✓ Full | ✓ Full |
| Email / Slack / Webhook Alerts | ✓ Full | ✓ Full |
| SSL Certificate Monitoring | ✓ Full | ✓ Full |
| Traffic Sampling | ✓ Full | API/GraphQL only |
| JS Error Collection | ✓ Automatic | Manual snippet required |
| Full Page Cache (FPC) Monitoring | ✓ Full | N/A if FPC bypassed |
Headless Setup: Manual JS Error Collection
Copy the snippet below into your frontend application's entry point — for example _app.js (Next.js), main.js (Vue/Nuxt), or your root layout.js. Replace YOUR_MAGENTO_DOMAIN with your store's actual domain.
(function(){
var _q=[],_t=null,_sent=0,_max=20,_sk='mm_js_sent',
_ep='https://YOUR_MAGENTO_DOMAIN/magemonitor/jserror/collect',
_seen=new Set();
try{_sent=parseInt(sessionStorage.getItem(_sk)||'0',10);}catch(e){}
function send(errs){
if(!errs.length||_sent>=_max)return;
errs=errs.slice(0,_max-_sent);
var x=new XMLHttpRequest();
x.open('POST',_ep,true);
x.setRequestHeader('Content-Type','application/json');
x.send(JSON.stringify(errs));
_sent+=errs.length;
try{sessionStorage.setItem(_sk,String(_sent));}catch(e){}
}
function queue(e){
var fp=e.message+':'+e.source+':'+e.line;
if(_seen.has(fp)||_sent>=_max)return;
_seen.add(fp);_q.push(e);
clearTimeout(_t);
_t=setTimeout(function(){send(_q.splice(0));},3000);
}
window.onerror=function(msg,src,line,col,err){
queue({message:String(msg),source:String(src||''),
line:line||0,
stack:err?String(err.stack||'').substring(0,2000):'',
url:location.href,ua:navigator.userAgent});
return false;
};
window.addEventListener('unhandledrejection',function(e){
var r=e.reason;
queue({message:r?(r.message||String(r)):'Unhandled rejection',
source:'',line:0,
stack:r&&r.stack?String(r.stack).substring(0,2000):'',
url:location.href,ua:navigator.userAgent});
});
})();
What the Snippet Does
- Catches uncaught JS errors via
window.onerror - Catches unhandled Promise rejections via the
unhandledrejectionevent - Batches errors with a 3-second debounce — never blocks your UI
- Deduplicates by message + source + line fingerprint
- Caps errors per browser session at its
_maxvalue. Edit that value to change the cap — the snippet runs outside Magento and cannot read the JS Errors Per Session setting - Uses
sessionStorageto track the per-session cap across page navigations - All collected errors appear in the MageMonitor dashboard → JS Errors tab exactly the same as errors from a native Magento frontend
This is the same collector MageMonitor injects into native Magento pages, with the RequireJS hook removed — headless frontends do not use RequireJS.
Server-Side Collection Limits
The collector endpoint applies its own limits, to both native and headless stores. They are the usual explanation when an error you expected does not appear in the dashboard:
- At most 10 errors are stored per request. Larger batches are truncated.
- At most 50 errors and 5 requests per minute, per client IP address. Beyond that the endpoint returns HTTP 429.
- The endpoint stops accepting new errors once the table holds 50,000 rows.
- Repeats of an error already stored increment its counter instead of creating a new row.
X-Forwarded-For header first.CORS Configuration
If your headless frontend is served from a different origin than your Magento backend — for example, your storefront is at shop.example.com and Magento at api.example.com — your web server must allow cross-origin requests to the collector endpoint.
Because the snippet sends Content-Type: application/json, this is not a CORS "simple" request: the browser first sends a preflight OPTIONS request. Magento does not answer OPTIONS on this route, so your web server must answer it. Both configurations below do this. Handling only the POST is the most common mistake — the browser blocks every request before Magento ever sees it.
Apache — add near the top of pub/.htaccess, above Magento's existing rewrite rules. Replace YOUR_FRONTEND_DOMAIN with your exact frontend origin.
# Answer the CORS preflight before Magento's front controller sees it
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_METHOD} =OPTIONS
RewriteCond %{REQUEST_URI} ^/magemonitor/jserror/collect
RewriteRule ^ - [R=204,L]
</IfModule>
<IfModule mod_headers.c>
SetEnvIf Request_URI "^/magemonitor/jserror/collect" MM_CORS=1
Header always set Access-Control-Allow-Origin "https://YOUR_FRONTEND_DOMAIN" env=MM_CORS
Header always set Access-Control-Allow-Methods "POST, OPTIONS" env=MM_CORS
Header always set Access-Control-Allow-Headers "Content-Type" env=MM_CORS
Header always set Access-Control-Max-Age "86400" env=MM_CORS
</IfModule>
<Location> and <LocationMatch> are only valid in server or VirtualHost config. Placing either in an .htaccess file makes Apache fail with "LocationMatch not allowed here" and returns HTTP 500 for every page of your store. Use the SetEnvIf form above in .htaccess; if you are editing your VirtualHost directly, you may wrap the Header lines in <LocationMatch "^/magemonitor/jserror/collect"> instead of using SetEnvIf.Nginx — this takes two pieces, because Magento serves the endpoint through an internal redirect to index.php, and Nginx applies add_header only in the location that finally generates the response.
# 1. In the http { } context (e.g. /etc/nginx/nginx.conf)
map $request_uri $mm_cors_origin {
default "";
~^/magemonitor/jserror/collect "https://YOUR_FRONTEND_DOMAIN";
}
# 2. In your Magento server { } block, above "location /".
# Answers the preflight; passes the POST on to Magento.
location = /magemonitor/jserror/collect {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "https://YOUR_FRONTEND_DOMAIN" always;
add_header Access-Control-Allow-Methods "POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type" always;
add_header Access-Control-Max-Age 86400 always;
return 204;
}
try_files $uri $uri/ /index.php$is_args$args;
}
# 3. Inside Magento's EXISTING PHP location — the one matching
# ^/(index|get|static|errors/report|health_check)\.php$ — add:
add_header Access-Control-Allow-Origin $mm_cors_origin always;
add_header Access-Control-Allow-Methods "POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type" always;
The map in step 1 makes step 3 safe: $mm_cors_origin is empty for every other URL, and Nginx omits a header whose value is empty. Only the collector endpoint receives CORS headers. Reload with nginx -t && systemctl reload nginx.
https://shop.example.com). Never use * — a wildcard lets any website on the internet POST errors into your dashboard.AWS Integration
Connect MageMonitor to AWS CloudFront, WAF, and CloudWatch for CDN analytics, WAF event monitoring, and infrastructure metrics. Navigate to Stores → Configuration → PointOfCode → MageMonitor → AWS Integration.
composer require aws/aws-sdk-phpus-east-1. Leave empty for auto-detection on EC2.E1ABCDEF123456. Leave empty if not using CloudFront.Cloudflare Integration
Connect to Cloudflare for CDN analytics, cache statistics, and WAF event monitoring. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Cloudflare Integration.
dash.cloudflare.com with these permissions: Zone → Analytics:Read AND Zone → Firewall Services:Read. Do NOT use your Global API Key — use a scoped token for security.SSL Certificate Monitoring
Automatic SSL certificate expiry monitoring for all store domains. Navigate to Stores → Configuration → PointOfCode → MageMonitor → SSL Certificate Monitoring.
Advanced Settings
Low-level controls for scanning behavior, HTTP monitoring, and data retention. Navigate to Stores → Configuration → PointOfCode → MageMonitor → Advanced Settings.
sudo for systemctl and usermod.Understand what that means before enabling it: any person or process able to reach an authenticated admin session gains the ability to restart system services on this host. If that is not a trade you want, leave this off — every other Quick Fix, and all detection, works normally without it. The two actions simply report that they are disabled, and their fix instructions give the command to run by hand instead.
User Roles & Permissions
Every dashboard tab, every tool and the settings screen is a separate permission. You can give an admin user exactly one tab and nothing else. Navigate to System → Permissions → User Roles, open a role, choose the Role Resources tab, set Resource Access to Custom, and tick what that role should see under MageMonitor.
How Permissions Are Enforced
Each permission is checked in three places, so a hidden tab is genuinely inaccessible rather than merely invisible:
Available Permissions
All of these live under MageMonitor in the Role Resources tree.
Dashboard Tabs
| Permission | Grants access to | Contains |
|---|---|---|
| Overview | Overview tab | Health score, category cards, critical and high issues |
| Backlog | Backlog tab, and the Move to backlog / Restore buttons (together with Resolve / Acknowledge Issues) | Findings deferred to later; they do not count in the score or alerts |
| Timeline | Timeline tab | Health score trend, open issues over time, recurring findings and the detection/resolution history |
| Live Metrics | Live Metrics tab | CPU, RAM, disk, PHP-FPM workers, live slow queries |
| Uptime | Uptime tab | Availability, incidents, response times and SLA reports |
| Server | Server detection tab | PHP, Redis, OPcache, disk, web server findings |
| Magento System | Magento detection tab | Cache, indexer and configuration findings |
| Database | Database detection tab | Table sizes, cleanup opportunities, slow queries |
| Frontend | Frontend detection tab | Storefront and JavaScript findings |
| Extensions | Extensions tab | Third-party module inventory, errors per extension and conflicts |
| Module Performance (under Extensions) | Slowest Extensions section of the Extensions tab | Extensions ranked by slow PHP time from the PHP-FPM slow log |
| Performance | Performance detection tab | Minification, FPC bypass, TTFB, log size |
| Search | Search tab | Search engine health and query findings |
| Security | Security tab | Security audit and grade, admin accounts, failed logins, file integrity |
| Cron Health | Cron Health tab | Cron heartbeat, failing jobs with their errors, every job's schedule and history |
| Cache Health | Cache Health tab | Varnish, Redis, FPC and OPcache health |
| Slow Requests | Slow Requests tab | Slowest storefront and admin URLs |
| JS Errors | JS Errors tab | JavaScript errors collected from visitor browsers |
| CDN | CDN tab | CloudFront / Cloudflare cache statistics |
| WAF | WAF tab | Firewall block activity and blocked IP addresses |
| SSL Certificates | SSL Certs tab | Certificate expiry per domain |
| Infrastructure | Infrastructure tab | Instance, region and hosting details |
| Live Traffic | Live Traffic tab | Requests in progress, visitor IP addresses, status codes |
| Server Advisor | Server Advisor tab | Sizing and tuning recommendations |
| Audit Log | Audit Log tab | Record of who ran what and when |
Actions and Tools
| Permission | Allows the user to | Recommended for |
|---|---|---|
| Run Scans | Trigger a scan from the dashboard instead of waiting for cron | Anyone who needs current data on demand |
| Resolve / Acknowledge Issues | Mark a finding resolved, which hides it until a scan detects it again. With the Backlog permission as well, also move findings to the backlog and restore them | Whoever owns triage — this changes what everyone else sees |
| Quick Fixes | Run the one-click fixes: flush cache, reindex, clear logs and the rest | Technical staff only. These change the running store. |
| Health Report | Generate and download the full health report | Anyone who reports to management or a client |
| Settings | Open and change MageMonitor configuration | Administrators only. Includes alert recipients and API credentials. |
Example Roles
| Role | Tick these | Result |
|---|---|---|
| Store Manager | Overview, Uptime, SSL Certificates, Health Report | Sees whether the store is healthy and online, and can send a report. No server internals, no visitor data, no fixes. |
| Developer | Everything except Settings and Live Traffic | Full diagnostic access including Quick Fixes, but cannot change alert recipients or API credentials, and cannot see visitor IP addresses. |
| Security Officer | Overview, Security, WAF, Live Traffic, Audit Log | Sees failed logins, file changes, firewall activity and who did what — and nothing about performance or the database. |
| External Agency | Overview, Performance, Slow Requests, Extensions, Run Scans | Enough to diagnose and prove a speed problem, with no access to security data, customer traffic or your configuration. |
Overview Tab
The landing page of the dashboard: the store’s health score and what is behind it, the health of each area, and every open finding, most serious first.
- Health score: the score with its rating and change against yesterday’s average, a one-sentence verdict, the calculation (100 minus the points each open finding takes off), when the last full scan ran, and the score over the last 7 days. Gaps in the line are hours when no score was recorded.
- Severity counts: open critical, high, warning and info findings. Click one to list only that severity.
- Health by Area: one card per area the admin can open (Server, Magento, Database, Frontend, Extensions, Performance, Search, Security, Cron, Cache) with its status and open findings by severity. Click a card to open that tab.
- Open Findings: critical, high and warning findings by default (switch to All to include info notes), each with its area, when it was detected and last confirmed, How to fix, Move to backlog and Resolve.
The top bar shows when the last full scan ran.
Health Score
The circular score (0–100) reflects the overall health of your store:
| Score Range | Color | Meaning |
|---|---|---|
| 90–100 | Green | Excellent — no significant issues |
| 70–89 | Green | Good — minor warnings present |
| 50–69 | Orange | Needs Attention — high-severity issues to address |
| 30–49 | Red | Poor — multiple serious issues |
| 0–29 | Red | Critical — requires immediate action |
How the score is calculated
The score starts at 100 and each open finding subtracts points according to its severity. Resolved findings cost nothing.
| Severity | Points deducted per finding |
|---|---|
| Critical | 25 |
| High | 10 |
| Warning | 3 |
| Info | 1 |
The score is floored at 0, so a store with many findings cannot go negative. A finding is counted once no matter how many times it has recurred — a warning seen 4,000 times still costs 3 points, not 12,000. The occurrence count tells you how persistent a problem is, not how much it costs.
Worked example: a store with 8 open warnings and 6 open informational findings has lost (8 × 3) + (6 × 1) = 30 points, giving a score of 70 — Good.
Health score on Magento's own dashboard
The score also appears as a compact widget at the top of Magento's built-in Dashboard (Dashboard in the admin menu), so you see it on login without opening MageMonitor. It shows the current score, the count of open findings by severity, and links straight through to the MageMonitor dashboard.
The widget is shown only to admin roles that hold the
PointOfCode_MageMonitor::dashboard permission, and it disappears entirely when
MageMonitor is switched off in configuration.
Category Cards
Each category card lists its open findings by severity (for example “2 high · 5 warning”) with a dot in the colour of the most severe one: red for critical, orange for high or warning, blue when only informational findings are open, and green when the category is clear. Clicking a card opens that tab. Categories: Server Health, Magento System, Database, Frontend/JS, Extensions, Performance, Security, Search, Cron Health and Cache Health.
Critical & High Issues
All detections with severity Critical or High are listed here with their problem description, how-to-fix instructions, and action buttons. Use Mark as resolved to hide an issue until a scan detects it again, or Move to backlog to defer it (see Backlog Tab).
Backlog Tab
Findings you have decided to deal with later — a PHP or Magento upgrade, a server change that needs a maintenance window. They stay tracked, but stop costing you health-score points and alert emails in the meantime.
- Move to backlog appears next to Mark as resolved on every open finding, in the category tabs, on the Overview and in the How to fix window. The finding moves to this tab and the sidebar shows how many are waiting.
- Restore puts a backlogged finding back on the open list, where it counts in the score and alerts again.
How a Backlogged Finding Behaves
| Question | Answer |
|---|---|
| Does it lower the health score? | No |
| Does it send alerts? | No. Moving it to the backlog is not reported as “resolved” either |
| Is it still checked? | Yes, on every scan, exactly like an open finding |
| What if the problem is fixed? | It resolves on its own, silently |
| What if it gets worse? | If its severity rises (for example Warning to Critical) it returns to the open list and alerts as an escalation |
| Is it deleted by the cleanup cron? | No. Only resolved findings older than the retention period are deleted |
Access needs the Backlog permission under Dashboard Tabs plus Resolve / Acknowledge Issues to move findings in or out — see User Roles & Permissions. Every move is recorded in the Audit Log.
Timeline Tab
How store health changed over the last 24 hours, 7 days or 30 days: the health score, how many issues were open, every finding that was detected or resolved, and the findings that keep coming back.
| Section | What it shows |
|---|---|
| Summary | The health score now and how it moved since the start of the period, the lowest score and when it happened, issues open now by severity, and how many findings were detected and resolved (with the typical time to resolve) |
| Health Score | The score saved every hour (averaged per 3 hours on the 7-day view and per 12 hours on the 30-day view), drawn over the Good / Needs attention / Poor bands. Grey periods have no score because cron was not running |
| Open Issues | How many issues were open at any time in each period, stacked by severity. A long-running issue counts in every period it was open, and one that opened and cleared within the hour still shows up |
| Recurring Findings | Findings detected more than once in the period, with how often, how long they were open in total and whether they are open now |
| Activity | Every detection and resolution, newest first and grouped by day, filterable by event type and category. Each entry links to its tab and shows how long the issue was open |
The tab only shows categories your admin role can view. Resolved findings are deleted after the Data Retention period (Advanced settings, default 30 days); when the selected period is longer than that, the tab warns that older issue counts are incomplete. Times are shown in your browser’s time zone.
Live Metrics Tab
What the server is doing right now: CPU, memory, disk, PHP-FPM, OPcache and database activity, refreshed every 10 seconds while the tab is open. Use Pause to freeze the numbers; polling also stops while the browser tab is in the background.
A banner at the top lists every metric that needs attention, or confirms that everything is within normal range. Each card has a coloured top edge (green, amber, red) and CPU, memory, connections and response time draw a trend line from the samples taken while the tab is open.
| Card | What it shows | Flagged when |
|---|---|---|
| CPU usage | Real CPU usage measured over a quarter of a second, plus I/O wait, steal time and load average | 70% (warning), 90% (critical); I/O wait above 20% or steal above 10% |
| Memory | Used and available RAM (available includes reclaimable page cache) and swap in use | 85% / 95% used |
| Disk | One card per filesystem holding the root, var/ and pub/media directories | The Server Health disk thresholds (default 15% / 5% free) |
| PHP-FPM workers | Busy workers against pm.max_children. Without the FPM status page only running processes (busy and idle) can be counted, so the card is informational | 80% / 95% busy (status page only) |
| OPcache | Memory used, cached scripts, hit rate, wasted memory and restarts for the PHP-FPM pool | Disabled or full (critical), 90% used (warning) |
| DB connections | Connections against max_connections, queries running now, and the peak since the database started | 60% / 80% |
| DB response time | Round trip of a trivial query | 50 ms |
| Database size | Data and index size, InnoDB buffer pool size, and headroom when DB Total Storage (GB) is configured | 70% / 85% of allocated storage |
Slow Queries Running Now
Client queries running longer than the Slow Query Threshold in the Database configuration (default 10 seconds), with user, database, state and SQL. Database background threads (the event scheduler, replication) are never counted. Admins with Quick Fixes access can kill them from here.
Top Processes
The processes using the most CPU at this moment (100% = one full core), with memory, owner and command line. Passwords, tokens and API keys in command lines are masked.
Host
Hostname, operating system, kernel, uptime, CPU model and cores, PHP version and memory limit, and the database version and uptime. On a multi-server setup the metrics describe the web server that answered the request, named in the banner. Configuration recommendations are in the Server Advisor.
Uptime Tab
Current status, 90-day availability, response times, incidents and a monthly SLA report for every monitored endpoint.
The uptime check runs every 3 minutes from Magento cron. A response below 500 counts as up (redirects, 401 and 403 mean the service answered); a 5xx error, timeout or no connection counts as down. An outage is confirmed after the configured number of consecutive failures (default 2), and an email is sent on DOWN and RECOVERY when downtime notifications are enabled. All times are shown in the Alert Timezone.
| Section | What it shows |
|---|---|
| Status banner | All systems operational, degraded (a check failed but is not yet confirmed), partial or major outage — or Monitoring has stopped when no check has run recently because cron is not running |
| Summary | 30-day uptime, confirmed incidents, total downtime and monitoring coverage (how much of the period was actually checked) |
| Endpoints | Per endpoint: current status and last result, a 90-day daily availability bar, uptime for 24 hours / 7 / 30 / 90 days, incidents and downtime, average, p95 and slowest response, and a 24-hour response-time chart |
| Incidents | Consecutive failed checks grouped into incidents with start, duration, cause and recovery. Single failed checks that recover immediately are listed as blips (hidden by default). When monitoring stopped after a failure, the duration shows the observed minimum (≥) instead of counting the unmonitored time as downtime |
| Monitoring gaps | Periods with no checks at all. Uptime percentages only count checks that ran, so gaps are listed separately rather than hidden |
| Monthly SLA report | Per month: uptime, pass/fail against a selectable SLA target (99.99% – 99%), downtime, incidents, average response and coverage, with CSV export of every check |
Detection Tabs
Each detection category has its own tab in the sidebar. Every tab (including Security and Cron Health) opens with a count of open findings by severity and a What this tab checks list, followed by one card per open finding.
Each card shows the problem in plain language, when it was first detected and when a scan last confirmed it, and a How to fix button with step-by-step instructions. Mark as resolved hides a finding until a scan detects the problem again; findings also resolve on their own once the check passes. Move to backlog defers a finding you plan to handle later (see Backlog Tab). A check that cannot be completed (for example when the storefront cannot be reached from cron) leaves its findings unchanged rather than resolving them.
| Tab | What It Monitors | Scan Frequency |
|---|---|---|
| Server | PHP version and extensions, PHP memory limit, PHP-FPM worker saturation and log warnings, free disk space (one finding per disk), Redis version, fragmentation, connections and restarts, session Redis, Varnish reachability, web server configuration (nginx upload size, Apache modules), MySQL version and buffer pool, health check endpoint, CloudFront errors, unexplained CPU-heavy processes | Every 5 min (configurable) |
| Magento | Deploy mode (developer and default mode), disabled or invalidated cache types, every indexer (reindex required, stuck in processing for over two hours, scheduled backlog that stopped moving), file-based sessions, and order confirmation emails that were never sent. Below the findings the tab shows the deploy mode, every indexer with its mode and queued changes, every cache type, and errors from exception.log and system.log over the last 7 days grouped by message with counts and stack traces | Every 15 min (configurable) |
| Database | Concurrent slow queries (same threshold as the live list), deadlocks in the last 7 days (needs the MySQL PROCESS privilege), connection pool usage, tables with 200 MB+ reclaimable space (only with innodb_file_per_table), database volume or configured storage close to full, changelog and log-table growth, missing indexes. Below the findings: database size, estimated rows, reclaimable space and buffer pool coverage, slow queries running now, the 20 largest tables with a copyable OPTIMIZE TABLE where a rebuild is worthwhile, and cleanup opportunities | Every 30 min |
| Frontend | JavaScript errors on checkout pages in the last 24 hours (high from 3 occurrences, critical from 10), spikes in distinct errors within an hour, and errors still occurring that exceed the recurring-error threshold. Browser-extension and autofill noise is ignored | Every 15 min |
| Extensions | Extensions that logged 10 or more errors in the last 7 days and are still failing (each error is attributed to the first third-party extension in its stack trace, or to the class named in the message, never to Magento core), known conflicting pairs, and empty generated PHP files. Below the findings: every installed extension with status, version, how it was installed, its error count and, when the PHP-FPM slow log is enabled, its slow requests and PHP time. Under that, Slowest Extensions ranks extensions by the PHP time they caused over the last 7 days (see below) | Every 10 min |
| Performance | Homepage time to first byte (median of three requests after a warm-up, when TTFB checks are enabled), full page cache misses where Magento exposes them, JS/CSS minification, debug logging (as Magento actually applies it: from app/etc/env.php, on by default outside production mode), log directory size, PHP-FPM slow log, slow admin grid queries, flat catalog and Varnish recommendations for large catalogs | Every 20 min |
| Search | Whether the configured search engine answers, tested with Magento’s own search client (same host, port, HTTPS and credentials as the storefront), OpenSearch cluster status (YELLOW is informational on a single node, where replica shards can never be placed), popular search terms from the last 90 days with no results, and search term table bloat | Every 6 hours |
| Security | 39-check security audit: admin access, patching, web exposure, malware indicators, storefront, API, live threats | Every 15 min (exposure & malware scans every 6 hours) |
| Cron Health | Cron not running, failing jobs (with cause and fix), backlog, stuck jobs, schedule bloat, root ownership. The tab also shows a live heartbeat, 24-hour failure trend, every failure grouped by job and cause (still failing or recovered), and a searchable table of every cron job with its schedule, last run, last success, next run, run time and error/missed counts | Every 10 min |
| Cache Health | Varnish status and hit rate; Redis reachability, keys evicted since the previous scan (the Redis counter itself only resets on restart), memory against maxmemory (threshold set by Redis Memory High), eviction policy, and a page cache database that is still empty after MageMonitor requests the homepage; full page cache state and backend (Varnish recommended only for large catalogs); OPcache memory, file count and hit rate as the web server’s PHP sees them, with the hit rate judged only once OPcache has been warm for an hour after a PHP-FPM reload | Every scan |
Slowest Extensions (Extensions tab)
PHP-FPM writes a stack trace for every request that runs longer than request_slowlog_timeout. Each trace is blamed on the first third-party extension found walking out from the code that was executing, because the innermost frame is almost always Magento’s database or cache layer: where the time was spent, not who asked for it. A request that never touches an extension is blamed on the Magento core module. Each row shows total and average slow time (durations come from the PHP-FPM error log), the number of slow requests, the file and function where the extension was executing, and advice for that kind of code (plugin, observer, block or model). It has its own Module Performance permission, nested under Extensions in the role tree.
When the slow log is not enabled the section shows the two pool settings to add:
request_slowlog_timeout = 5s slowlog = /var/log/php8.2-fpm.slow.log
Reload PHP-FPM afterwards and make sure the web server user can read the file. A different location can be set under Performance Monitoring › PHP Slow Log Path.
Detection Severity Levels
Slow Requests Tab
Storefront and admin pages, REST calls and GraphQL resolvers that took longer than the Slow Page Threshold (ms) (Performance Monitoring, default 2000).
Every request is timed, including the time Magento spends rendering the page after the controller runs, so pages that are slow to render are caught. Timing is never sampled; the Sampling Rate setting only limits how many requests are written to the Live Traffic log. Only requests over the threshold are stored, one row per route, with the average and slowest time of those slow hits, how many times it happened and when it last did. Rows are kept for 30 days.
The tab shows a summary, the requests that were slow in the last 24 hours, and earlier ones. Admin secret keys and query strings are removed from the sample URLs shown.
JS Errors Tab
Real JavaScript errors collected from real visitors' browsers. The collector catches window.onerror, unhandledrejection, and require.onError events, batches them client-side, and sends them to MageMonitor every 3 seconds.
Stat Cards
- Occurrences — How many times errors occurred over the retained 14 days (click to show all errors)
- Distinct Errors — Number of different errors (same message, file and line) (click to show all errors)
- On Checkout — Occurrences on checkout, onepage and payment pages (click to filter to checkout only)
- Active in Last Hour — Distinct errors that occurred in the last 60 minutes (click to filter to recent)
Browser-extension, autofill and ResizeObserver noise is excluded from every card and from the list. Open an error to see the browsers and operating systems it occurred in, when it was first seen, the exact file and line, and the stack trace the browser sent. When the collector is switched off the tab says so, since no new errors can arrive.
Filtering
- Search box — Filter by error message, source file, or page URL in real time
- Page filter dropdown — Filter to a specific page or all pages
- Card click — Click any stat card to filter the table
Error Table
Errors are grouped by message + source file combination. Each row shows: error message, source filename, pages affected (with page count badge if multiple pages), total count, and last seen timestamp. The page column color-codes checkout (red), customer account (orange), and homepage (blue) for quick identification.
CDN Tab
CDN analytics from AWS CloudFront or Cloudflare. Shows cache hit rate, bandwidth, request volume, top cached URLs, and error rates. Requires AWS or Cloudflare integration to be configured.
WAF Tab
Web Application Firewall events from AWS WAF or Cloudflare. Shows blocked requests, triggered rules, and top blocked IPs. Requires AWS or Cloudflare integration to be configured.
SSL Certs Tab
Certificate status for every store view domain and any extra domains you configure: expiry, issuer, whether browsers trust it, whether it covers the domain name, and the HTTP protocol served.
MageMonitor reads the certificate first and verifies it separately, so an expired, self-signed, wrong-hostname or incomplete-chain certificate is reported with the reason (for example “The certificate expired 2026-01-12”) and raises a critical alert, instead of appearing only as a connection error. A domain that cannot be reached over TLS at all is also critical.
| Days Remaining | Status | Alert Sent |
|---|---|---|
| 30+ days | Valid | No alert |
| 7–29 days | Warning | WARNING alert |
| 1–6 days | Critical | CRITICAL alert |
| 0 or expired | Expired | CRITICAL alert |
Infrastructure Tab
The server, services and software the store runs on, detected automatically. Use Refresh to read it again.
- Resources: CPU load as a share of the CPU cores (with the 1, 5 and 15 minute load averages), memory, swap and the fullest disk. Cards turn amber or red as they fill. The history of these values is on the Live Metrics tab.
- Server: whether it is a virtual machine, container or physical server, the provider when it can be identified, hostname, IP address, operating system and uptime.
- Magento: version and edition, deploy mode, where sessions and cache are stored, and the store URLs.
- Services: MySQL/MariaDB (with database size), Redis, the search engine and PHP-FPM, each with its status, version and address.
- Storage: every filesystem Magento uses with used, free and total space, plus the size of Magento’s log and cache files.
- PHP: the settings of the PHP that serves the store (version, memory limit, execution time, upload size, display errors, OPcache and its hit rate), every extension Magento 2.4 requires with any missing ones listed first, and optional extensions (
redis,imagick) that make Magento faster but are not required.
Live Traffic Tab
Who is on the store right now. The tab refreshes every 2 minutes; Refresh reloads it immediately.
- Summary: active visitors (distinct real browsers in the last 30 minutes), storefront and API requests in the last 30 minutes with their average response time, and the share of traffic from bots over the last 2 hours.
- Recent Visitors: one row per visitor (IP address and browser) seen in the last 30 minutes, with device, whether it is a bot, how many requests it made, the last page, average response time and when it was last seen.
- Top Requests: the most requested storefront pages and REST/GraphQL endpoints over the last 2 hours. The same page with different query strings counts as one.
- Bots: real browsers versus bots, grouped into search engines, AI crawlers, SEO tools, scrapers and scanners, and monitoring services, with each bot’s requests.
- Admin Activity: the admin pages opened in the last 2 hours (background calls such as grid data and dashboard refreshes are left out, and secret keys are removed from URLs) and the admins signed in during the last 15 minutes.
Requests are logged as Magento serves them, so pages served entirely by Varnish or a CDN are not counted. Below 1,000 requests an hour every request is logged; above that only the Sampling Rate share is, and the tab says the counts are a sample. MageMonitor’s own checks (uptime, security audit, cache and performance probes) are not logged. Anything that is not a real browser counts as a bot.
Quick Fixes
Maintenance actions you can run from the dashboard. Each action shows what it affects before you run it, and every run is recorded in the Audit Log with your username and the result.
Actions that do not apply to the store are shown disabled with the reason: code and static-file clearing in production mode, PHP-FPM and Varnish actions when Privileged Quick Fixes are off, and CloudFront invalidation without the AWS Integration. Actions that delete data or lock tables ask for confirmation first.
| Group | Action | What it does | Impact |
|---|---|---|---|
| Cache | Flush all caches | Clears every Magento cache type. Pages load more slowly for a few minutes while the cache refills. | Briefly slower |
| Cache | Enable all cache types | Turns back on any cache type that was switched off. | No downtime |
| Cache | Warm the page cache | Requests the homepage and top category pages of every active store view. | No downtime |
| Cache | Clear generated code | Deletes generated/code. Not available in production mode, where bin/magento setup:di:compile must be run instead. | Briefly slower |
| Cache | Clear static files | Deletes generated CSS, JavaScript and images. Not available in production mode, where static content must be deployed instead. | Briefly slower |
| Indexing | Reindex invalid indexers | Rebuilds only the indexers Magento has marked as needing a reindex. | Briefly slower |
| Indexing | Reindex everything | Rebuilds every indexer in the background; View reindex progress shows its log. | Stale data until done |
| Indexing | Truncate changelog tables | Empties indexer changelog (*_cl) tables above the configured size threshold, then reindexes what they fed. | Stale data until done |
| Database | Optimize fragmented tables | Rebuilds up to 5 tables with over 100 MB, and over 30% of their size, reclaimable. | Locks tables briefly |
| Database | Kill slow queries | Stops queries still running past the slow-query threshold; their transactions are rolled back. | Rolls back queries |
| Database | Remove old inactive carts | Deletes carts converted to orders or closed and not updated for over a year. Orders keep their own copy. | Deletes data |
| Database | Clean cron history | Deletes finished, missed and failed cron entries older than 7 days. | Deletes data |
| Server | Maintenance mode | Shows its current state and turns it on or off. Your IP address stays allowed while it is on. | Store briefly offline |
| Server | Clear stuck cron jobs | Removes schedule entries left “running” for over 3 hours so those jobs can run again. | No downtime |
| Server | Empty large log files | Empties every file in var/log larger than 10 MB. | Deletes data |
| Server | Restart PHP-FPM | Frees workers stuck on slow requests. Needs Privileged Quick Fixes (Advanced Settings) and sudo access for the web server user. | Store briefly offline |
| Server | Allow reading Varnish statistics | Shown only when Varnish is running and MageMonitor cannot read its statistics. Needs Privileged Quick Fixes. | Store briefly offline |
| Server | Invalidate CloudFront cache | Asks CloudFront to fetch the paths from the CloudFront finding again. Needs the AWS Integration. | Briefly slower |
| MageMonitor | Send a test email | Sends a sample alert to the first address in Email Alerts › Alert Recipients, to confirm delivery. | No downtime |
| MageMonitor | Send a test Slack message | Posts a sample message to the configured Slack webhook. | No downtime |
| MageMonitor | Run alert check now | Sends alerts for findings that are new or changed since the last alert, without waiting for the schedule. Nothing is sent when nothing changed. | No downtime |
| MageMonitor | Clear findings history | Deletes every finding after showing how many there are. Traffic, uptime history and settings are kept. | Deletes data |
| MageMonitor | Reset all MageMonitor data | Deletes everything MageMonitor has collected after showing record counts per table; type RESET to confirm. The license and settings are kept. | Deletes data |
Server Advisor
Compares the server’s PHP, OPcache, database, Redis, web server and hardware settings with what a store of this size needs.
Store size is small, medium or large, set by product count, orders in the last 30 days and database size; recommendations such as memory limits, buffer pool size, CPU cores and RAM scale with it. The page opens with counts of settings needing action, recommended improvements and passing checks, then lists the recommendations most important first, each with the current and recommended value and a copyable fix. All Checks lists every setting by area.
- PHP: version and end of security support, memory limit, execution time, form field limit (
max_input_vars), upload size, realpath cache and every extension Magento 2.4 requires. - OPcache: enabled, hit rate (judged once OPcache has run for an hour after a restart), memory, file slots and timestamp validation.
- Database: version, InnoDB buffer pool against database size, connection use, slow query log, query cache and how often the table cache misses.
- Redis: read directly from Redis (no PHP extension needed): version, whether a memory limit is set, and the eviction policy.
- Web server: server software, HTTPS, compression and HTTP/2 measured on a real storefront request, and Varnish for larger stores.
- Server: free disk space, CPU cores, RAM and deploy mode.
Audit Log
Who changed what through MageMonitor, and when: quick fixes, settings changes, findings marked resolved, acknowledged or reopened, scans, health reports and file-baseline resets, plus the alert emails MageMonitor sent.
- Summary: actions in the selected period, the admins who made them, disruptive actions (ones that deleted data or interrupted the store) and alert emails sent.
- Filters: period (24 hours to 90 days), type (disruptive, maintenance, findings, settings, scans and reports, alert emails), admin and a text search. Alert emails are left out unless chosen, so they do not bury admin actions.
- Entries are grouped by day, newest first, 100 at a time, each coloured by type.
- Settings changes list which MageMonitor settings were changed, never their values, because several are secrets (webhook URLs, API tokens, AWS keys).
- Export CSV downloads the entries matching the current filters, with times in the alert timezone.
Actions run by cron or the command line show as System. Entries are kept for 90 days.
Health Report
A complete store health report as a printable page. Click Report in the MageMonitor header to open it, then Save as PDF to keep or share it (A4, page breaks between sections).
- Cover: store name and URL, when the report was generated (in the alert timezone), Magento version, edition and deploy mode, PHP and MageMonitor versions, and the health score with its rating and change against yesterday’s average.
- 1. Summary: a one-sentence verdict, open findings by severity, key indicators (7-day uptime, security grade, cron status and SSL expiry), the health of each area, and up to five priority actions linked to their findings.
- 2. Findings: every open finding once, most serious first, with what is wrong, how to fix it (commands shown as copyable code), and when it was first and last detected.
- 3. Details by Area: server resources and PHP, database size, connections and largest tables, cache (page cache, Varnish, Redis, OPcache), cron status and jobs still failing, uptime per endpoint with recent incidents, SSL certificates, the slowest requests, JavaScript errors (browser-extension noise excluded) and the security audit by area.
Figures come from the same data as the matching dashboard tabs. An admin sees only the areas their role can open, and generating a report is recorded in the Audit Log.
All Detectors
MageMonitor includes 10 specialized detectors. Each detector runs independently with its own try/catch error handling — a failure in one detector never affects others.
Server Detector
Runs every 5 minutes (configurable). Checks the PHP version and extensions and the PHP memory limit, PHP-FPM worker saturation, free disk space (the root disk, var/ and pub/media, reported once per physical disk), Redis version, fragmentation, connections and restarts, session Redis reachability, Varnish reachability, web server configuration, MySQL version and buffer pool sizing, the health check endpoint, CloudFront errors and unexplained processes using sustained CPU.
Scheduled scans and PHP settings. Scheduled scans run in PHP's command-line interpreter, which has its own php.ini, usually no OPcache and no memory limit. So that PHP findings describe the PHP that actually serves your store, MageMonitor reads PHP-FPM's settings through its token-protected health endpoint (/magemonitor/health/). If the storefront cannot be reached from the server (for example behind HTTP authentication), these checks are skipped and their findings stay as they were. OPcache and Redis cache memory are reported under Cache Health, the search engine under Search, and cron under Cron Health, so no problem is reported twice.
Magento Detector
Runs every 15 minutes (configurable). Checks the deploy mode, every cache type (disabled or left invalidated), every indexer (reindex required, stuck in processing, scheduled backlog not moving), file-based session storage, and order confirmation emails that were due but not sent (orders with confirmations enabled whose email was never marked sent, including failed asynchronous sends). Asynchronous grid indexing is checked by the Database detector.
Database Detector
Runs every 30 minutes. Checks database storage utilization, live slow queries from PROCESSLIST, missing indexes on high-impact tables (url_rewrite, sales_order_address), table fragmentation (>30% waste AND >200MB recoverable), async grid indexing, and orders grid size.
Frontend Detector
Runs every 15 minutes. Analyzes the JS error log for checkout errors, error spikes (unusual increase in error volume), and recurring high-frequency errors that degrade user experience.
Extensions Detector
Runs every 10 minutes. Checks for disabled modules that other modules depend on, known conflicting extension combinations, and modules with known performance issues.
Performance Detector
Runs every 20 minutes. Checks flat catalog configuration vs product count, Full Page Cache backend (recommends Varnish at scale), Redis maxmemory configuration, InnoDB buffer pool vs available RAM, and OPcache sizing.
Search Detector
Runs every 6 hours. Checks Elasticsearch/OpenSearch cluster health (yellow/red status), shard assignment, and search query table growth with intelligent junk ratio analysis (flags only when >40% of rows are one-time queries older than 90 days).
Security Detector (Security Center audit)
Runs every 15 minutes. Web exposure probes and the malware file scan reuse their result for 6 hours (use Re-run Full Audit in the Security tab to refresh them immediately). The audit produces a 0–100 score and A–F grade, and every failed check becomes a finding with evidence, why it matters, the exact fix and the matching standard (PCI DSS v4.0, OWASP).
| Area | Checks |
|---|---|
| Active Threats | Brute force / failed admin logins, admin accounts created in the last 7 days, critical file integrity, cron jobs pointing at unknown code |
| Malware Indicators | Executable scripts in pub/media and pub/static, unexpected PHP files in the web root, obfuscated or unknown-domain JavaScript in design configuration and CMS content, exploit directives in email templates |
| Web Exposure | Downloadable secrets (env.php backups, auth.json, .git, .env, SQL dumps, logs, phpinfo), HSTS / X-Frame-Options / X-Content-Type-Options headers, HTTP→HTTPS redirect, /magento_version disclosure |
| Admin Access | Two-factor authentication, guessable admin path, admin URL secret key, lockout, idle session timeout, account sharing, login CAPTCHA, password rotation, account hygiene (generic, abandoned or placeholder-email accounts), full-access roles |
| Platform & Patching | Magento patch level and release-line end of support, PHP end of security support, error details shown to visitors (display_errors overrides in entry points, pub/errors/local.xml print action, developer mode), database user privileges, Redis authentication, env.php and entry-point permissions |
| Storefront & Customers | HTTPS on every store view, HttpOnly cookies, checkout Content Security Policy enforcement, reCAPTCHA on login / registration / password reset / checkout, customer lockout, customer password rules, template hints and symlinks |
| API & Integrations | Anonymous REST access, integration tokens as bearer tokens, token expiry, integrations with full API access |
Cron Health Detector
Runs every 10 minutes. Checks whether cron is running at all, jobs failing on their latest run (with Magento's recorded error, the likely cause and fix), cron backlog count, stuck running jobs, cron_schedule table size, and whether cron is running as root.
Cache Detector
Runs every 10 minutes. Checks Varnish running status and hit rate (via varnishstat with layered fallback), Redis running status, memory usage, eviction policy, evicted keys count, and per-database key counts. Also checks Magento FPC backend configuration and OPcache hit rate and file count.
Background Jobs
MageMonitor registers 24 cron jobs that run automatically via Magento's cron system. All jobs are prefixed with poc_magemonitor_ and belong to the default cron group; the job code under each name is what you will see in cron_schedule and on the Cron Health tab. Each detection category has its own schedule, so a slow check never delays a fast one.
| Job | Schedule | What It Does |
|---|---|---|
ServerHealthpoc_magemonitor_server | Configurable (default: */5) | PHP-FPM, OPcache, disk, Redis health scan |
MagentoHealthpoc_magemonitor_magento | Configurable (default: */15) | Cache, indexers, Magento config scan |
DatabaseHealthpoc_magemonitor_database | */30 * * * * | DB storage, indexes, slow queries, fragmentation |
PerformanceCheckpoc_magemonitor_perf | */20 * * * * | FPC, flat catalog, Redis config checks |
FrontendHealthpoc_magemonitor_frontend | */15 * * * * | JS error analysis, checkout error detection |
SecurityCheckpoc_magemonitor_security | */15 * * * * | Security audit (brute force, file integrity, admin access, patching, exposure, malware indicators) |
CacheHealthpoc_magemonitor_cache | */10 * * * * | Varnish, Redis, Magento FPC and OPcache health |
CronHealthpoc_magemonitor_cronhealth | */10 * * * * | Stuck jobs, queue backlog, cron schedule table growth |
UptimeCheckpoc_magemonitor_uptime | */3 * * * * | HTTP health check of all monitored URLs |
AlertProcessorpoc_magemonitor_alerts | */5 * * * * | Sends email/Slack/webhook alerts for new detections |
FlushTrafficQueuepoc_magemonitor_flush_traffic | * * * * * | Writes queued traffic data from Redis/files to DB |
CleanTrafficDatapoc_magemonitor_clean_traffic | */5 * * * * | Removes traffic data older than 2 hours |
LogParserpoc_magemonitor_logparser | */10 * * * * | Runs the Extensions detector: attributes exception.log / system.log errors to the extension that caused them, and checks module conflicts |
SslCheckpoc_magemonitor_sslcheck | 0 */6 * * * | Checks SSL certificate validity and expiry |
SearchCheckpoc_magemonitor_search | 0 */6 * * * | Elasticsearch/OpenSearch health check |
HealthScoreSnapshotpoc_magemonitor_healthscore | 0 * * * * | Calculates and saves hourly health score |
FileIntegritypoc_magemonitor_filecheck | 0 */4 * * * | SHA-256 hash comparison for monitored files |
LicenseCheckpoc_magemonitor_license_check | */30 * * * * | Validates license key against registered domain |
StoreIntelligenceScanpoc_magemonitor_store_intelligence | 0 */3 * * * | Deep database/cron/performance intelligence scan |
Cleanuppoc_magemonitor_cleanup | 0 2 * * * | Daily cleanup of old data per retention policy |
Probe: SlowQueriespoc_magemonitor_probe_slow_queries | */2 * * * * | Samples database queries running right now |
Probe: FpmSaturationpoc_magemonitor_probe_fpm_saturation | */3 * * * * | Samples PHP-FPM worker saturation |
Probe: AdminGridpoc_magemonitor_probe_admin_grid | */3 * * * * | Detects admin grid queries stuck behind a slow JOIN |
Probe: RedisLoadpoc_magemonitor_probe_redis_load | */5 * * * * | Samples Redis operations per second |
www-data. Verify your cron is configured: sudo crontab -u www-data -l. If cron is not installed, run: sudo -u www-data php bin/magento cron:installNotifications
MageMonitor supports three notification channels, each configurable independently with their own digest schedule.
When an Alert Is Sent
The alert processor runs every 5 minutes. It does not send a message every time it runs — it sends one only when something about your store has genuinely changed. A finding has an identity (which problem it is) and a state (how severe it is), and those two things are the only reasons a message is ever sent.
| Trigger | What it means | Timing |
|---|---|---|
| New issue | A problem was detected that you have not been told about | Immediately, if it is Critical or High |
| Escalation | A problem you already know about has become more severe — a Warning that is now Critical | Immediately, if the new level is Critical or High |
| Resolved | A problem has cleared | After it has been absent from two consecutive checks |
| Health score drop | The score fell below your configured threshold | Once, on the way down — it re-arms when the score recovers |
| Scheduled report | The current state of the store, whether or not anything has changed | At fixed times of day — see below |
| Downtime / Recovery | A monitored URL stopped or started responding | Immediately, after the configured number of confirmations |
When an Alert Is Not Sent
This is the more important half, and it is a guarantee rather than a best effort.
Specifically, none of the following sends anything:
The Scheduled Report
Event alerts tell you what changed. The scheduled report tells you where the store stands — the full current picture, sent on a fixed clock whether or not anything has happened. It is configured separately for each channel, under Scheduled Report Frequency, Send the Scheduled Report and First Report of the Day At.
Three choices of when it is worth sending:
If a report is missed — cron was down, mail was refused — it costs you one report, not a backlog. The next run sends the current picture rather than replaying every window that went by. Setting the frequency to Off leaves the channel with event alerts only.
Subject Lines
The two kinds of email deliberately read differently, because you do different things with them.
| Kind | Subject | Why |
|---|---|---|
| Event alert | CRITICAL: Acme — 5 Concurrent Slow Queries (worst: 42s) |
It is announcing one specific thing that just happened. Naming it lets you decide whether to act straight from the phone notification, without opening the mail. |
| Scheduled report | MageMonitor Report: Acme — 12 open issues, 2 critical (health 58/100) |
It is not announcing anything — it arrives on a clock and describes the whole store. The shape is fixed so it is instantly recognisable and an inbox rule has something constant to match. |
Set an Email Subject Tag under Alert General Settings to put your own string in front of every MageMonitor email — for example [Store Monitor], giving subjects like [Store Monitor] MageMonitor Report: Acme — all clear (health 100/100). One rule on that tag then catches every monitoring email you receive, whatever it is about.
What an Alert Contains
Every alert shows the current health score and its movement since the last message you received. Below that:
The scheduled report is the exception: it prints everything in full, because it is the complete picture you asked for on a schedule rather than a notification about a change.
Webhook Payload Format
{
"event": "detection_alert",
"store": "My Store",
"health_score": 72,
"timestamp": "2026-06-13T10:00:00+02:00",
"detections": [
{
"code": "VARNISH_HIT_RATE_CRITICAL",
"severity": "critical",
"category": "cache",
"title": "Varnish Hit Rate Critical (18%)",
"problem": "Varnish cache hit rate is 18%...",
"how_to_fix": "Check VCL cookie stripping..."
}
]
}
Webhook payloads are signed with HMAC-SHA256 using your configured secret. Verify the signature on your endpoint by comparing the X-MageMonitor-Signature header against HMAC-SHA256(secret, payload_body).
Frequently Asked Questions
Does MageMonitor impact store performance?
MageMonitor is designed for minimal overhead. The traffic sampling plugin runs on a configurable percentage of requests (default 10%) with a cache-backed enablement check on every request. All heavy analysis runs via background cron, not during customer page loads. The JS collector snippet is under 2KB and uses a 3-second batch delay before sending.
Does MageMonitor modify any store data?
No. All detectors are strictly read-only — they only run SELECT queries against your database. The only writes MageMonitor performs are to its own tables (prefixed poc_magemonitor_). Quick Fix actions that modify data (cache flush, reindex) run standard Magento CLI commands and are explicitly triggered by admin users.
The health score is 0 but my store is working fine. Why?
This can happen immediately after installation, before the first cron scan completes — wait 5–10 minutes for the initial scans to run. If the score stays low after that, it is arithmetic rather than a fault: each open finding subtracts points by severity (see How the score is calculated above), and a store with many low-severity findings can score poorly while trading perfectly well. Open the category tabs to see what is counted. Informational findings cost 1 point each and are often safe to leave.
I see a false positive detection. How do I stop it?
Use Mark as resolved if you believe it is fixed (it comes back if the next scan still finds it), or Move to backlog to keep it out of the score and alerts while it stays tracked. For persistent false positives (e.g. Varnish hit rate warning on a store with many logged-in customers), adjust the relevant threshold in Configuration — for example, lower the Varnish Hit Rate Warning Threshold from 40% to 25%.
Can I install MageMonitor on multiple stores with one license?
Each license key is tied to one domain. For multiple stores (different domains), purchase a separate license for each. Multi-domain licenses are available — contact support at store.pointofcode.com.
Varnish stats show 0% hit rate but Varnish is running.
The www-data user does not have permission to read Varnish shared memory. Fix using the Quick Fix button: Quick Fixes → Fix Varnish Permissions. Or run manually: sudo usermod -a -G varnish www-data && sudo systemctl restart php-fpm
The "On Checkout" filter shows no errors but the count is non-zero.
Checkout errors are matched against URLs containing "checkout", "onepage", or "payment". If your store uses a custom checkout URL, the filter may not match. Search for the checkout URL pattern manually using the search box in the JS Errors tab.
The admin returns 500 errors after installing or updating.
setup:upgrade emptied pub/static and no setup:static-content:deploy followed. Run sudo -u www-data php bin/magento setup:static-content:deploy -f, then cache:flush. The storefront usually keeps working in the meantime because it is served from full-page cache.
Changes or an update have no effect.
PHP-FPM is still serving the previously compiled code. Run setup:di:compile, then reload PHP-FPM (for example sudo systemctl reload php8.2-fpm).
The dashboard never updates.
Almost always a stopped cron. sudo -u www-data php bin/magento cron:run should produce output, and the Cron Health tab shows when a job last started. Check also that Automatic Cron Scanning (Advanced Settings) and the module itself (General Settings) are enabled.
How do I uninstall MageMonitor?
Installed with Composer:
sudo -u www-data php bin/magento module:uninstall PointOfCode_MageMonitor --remove-data
sudo -u www-data php bin/magento cache:flush
This runs MageMonitor’s uninstall script, which drops all of its poc_magemonitor_* tables, deletes its magemonitor/* configuration rows and its licence record, and clears its entry from app/etc/env.php — including the magemonitor/health_secret key, so no credential is left behind. If env.php is not writable at the time, the uninstall still completes and the entry to remove by hand is written to the Magento log.
Installed manually in app/code: Magento runs uninstall scripts only for Composer packages, so remove the module and then its data yourself:
sudo -u www-data php bin/magento module:disable PointOfCode_MageMonitor
rm -rf app/code/PointOfCode/MageMonitor/
sudo -u www-data php bin/magento setup:upgrade
sudo -u www-data php bin/magento cache:flush
-- then, in MySQL (add your table prefix if you use one)
DROP TABLE IF EXISTS poc_magemonitor_detections, poc_magemonitor_js_errors,
poc_magemonitor_health_snapshots, poc_magemonitor_uptime, poc_magemonitor_admin_logins,
poc_magemonitor_file_hashes, poc_magemonitor_slow_pages, poc_magemonitor_maintenance_log,
poc_magemonitor_ssl_certs, poc_magemonitor_traffic;
DELETE FROM core_config_data WHERE path LIKE 'magemonitor/%';
DELETE FROM poc_core_license WHERE product_sku = 'POC-MAGEMONITOR-M2';
Finally remove the 'magemonitor' block from app/etc/env.php. Leave PointOfCode_Core installed if you use any other PointOfCode extension.