woocommerce Case study
A2 Egress Firewall
wp-admin was regularly taking ten seconds or more to render a page. The cause was not the database or PHP; it was WordPress dutifully waiting on outbound HTTP calls to plugin licence servers, font CDNs and update endpoints that are slow or simply unreachable from where the store is hosted.
The business problem
A WordPress install makes a surprising number of blocking outbound calls during an admin request: update checks, licence validation, template libraries, Gravatar, font APIs. From an Iranian host, several of those hosts time out rather than fail fast, and each one adds its full timeout to the page. The dashboard felt broken while every individual component was working as designed.
What I delivered
- a2-egress-firewall-adminspeed.php, a blocklist rather than an allowlist, so nothing that currently works breaks when the plugin is installed.
- A curated list of destinations known to hang from this host: plugin licence and update endpoints, template libraries, font and avatar APIs, and a CDN or two.
- A fail-fast path that drops the connect timeout to 1 second and the total timeout to 2 seconds for anything not blocked outright.
- A companion front-end module, a2-egress-assets-firewall.php, that catches external script and style URLs at script_loader_src and style_loader_src, with a monitor mode that logs without blocking.
- A bypass key and an admin-only switch, so the whole thing can be disabled for a single request when something genuinely needs to reach out.
Technical approach
- The block happens at pre_http_request, which returns a synthetic response before a socket is ever opened. Nothing waits.
- Host matching is suffix-based against a parsed host, not a substring search against the URL, so a blocked domain cannot be smuggled through in a query string.
- The site's own hostnames and anything resolving locally are explicitly exempted, because loopback requests are how WP-Cron and the REST API talk to themselves.
- Defaults are deliberately conservative: admin-only enforcement, logging off, and the asset firewall shipped in monitor mode so I could read the log before deciding what to block.
- One destination is documented in the source as deliberately not blocked, because it is an Iranian host that responds normally and blocking it would break a price integration.
Result and evidence
Admin page loads stopped stalling on outbound calls. I have not measured a clean before-and-after average because the delay was variable by nature, depending on which endpoints were unreachable that day; the defensible result is that the failure mode itself is gone, since blocked destinations now return instantly instead of consuming a full timeout.
Commercial value
This is the difference between a dashboard staff avoid and one they use. It also cut the store's exposure to third-party availability: an outage at a plugin vendor no longer becomes an outage in our admin.
Readable implementation brief
implementation_brief {
project: "A2 Egress Firewall"
files: "a2-egress-firewall-adminspeed.php (224 lines)
a2-egress-assets-firewall.php (84 lines)"
strategy: "blocklist, not allowlist"
hook: "pre_http_request -> synthetic response, no socket"
failfast: "connect 1s / total 2s for everything else"
scope: "wp-admin only by default; bypass key available"
frontend: "script_loader_src + style_loader_src, monitor mode"
exempt: "own hostnames and loopback, always"
}What this project shows
The tempting version of this project is a strict allowlist. I chose a blocklist because an allowlist on a live store with dozens of plugins is a guaranteed incident, and the blocklist reaches most of the benefit with a fraction of the risk.
Shipping the front-end half in monitor mode first came from the same instinct. I would rather read a week of logs than guess, especially when the failure mode is an invisible missing stylesheet.