API Testing Behind the Firewall: How Remote Executors Work

The hardest question for any cloud-based testing platform isn't about features. It's the one the security team asks in the first meeting:
"Our staging environment isn't reachable from the internet. How exactly is your SaaS going to test it?"
It's a fair question. API testing behind the firewall is where most SaaS test tools quietly give up. The APIs that matter most for catching regressions (staging, pre-production, internal pricing and inventory services, the ERP adapter nobody wants to touch) are exactly the ones that sit in a private network. If your test platform can't reach them, it can only tell you about problems once they hit production.
The traditional answers are all bad. Whitelisting the vendor's IP range means opening your perimeter to a third party. A site-to-site VPN is a months-long project with its own audit burden. Running the whole test platform on-premises means you lose the SaaS: no managed updates, no shared dashboards, no cross-team visibility.
Four ways to test internal APIs from a cloud platform
Before looking at how remote executors work, it helps to put the options side by side. Every team that wants to test internal APIs with a hosted tool ends up choosing one of these:
| Approach | Network change | Who owns the risk | Typical lead time | Main drawback |
|---|---|---|---|---|
| IP allowlist | Inbound rule from the vendor's IP range to your APIs | You, for every IP the vendor might ever use | Days to weeks (firewall change request) | A permanent hole in the perimeter; breaks when vendor IPs change |
| Site-to-site VPN | Tunnel between your network and the vendor's | Shared, and audited on both sides | Weeks to months | Heavy to set up and maintain; often scoped wider than needed |
| Self-hosted platform | None, it all runs inside | You, for the whole application | Weeks, then ongoing | You operate, patch and upgrade the test platform yourself |
| Remote executor | None inbound; outbound HTTPS only | You, for one small, stateless process | Minutes to hours | Needs somewhere to run inside the network (a VM, container or laptop) |
The executor model wins because it changes direction, not just tooling. Nothing on the internet initiates a connection into your network. That single property is what makes the conversation with security short.
The remote executor model
A remote executor inverts the connection. Instead of the cloud reaching into your network, a lightweight agent inside your network reaches out:
- You run a small executor process anywhere inside the private network - a developer laptop, a CI runner, a container in your cluster.
- The executor authenticates with a scoped API key and polls the cloud platform over outbound HTTPS for pending jobs.
- A job is nothing more than a batch of HTTP requests to execute: method, URL, headers, body.
- The executor runs the requests against your internal APIs - traffic that never leaves your network - and posts the responses back over the same outbound channel.
The security profile is what makes this work in enterprise environments:
- No inbound firewall rules. Nothing listens. There is no port to open, no tunnel to maintain.
- No VPN. The only network requirement is that the executor can make HTTPS calls out - the same requirement as any workstation browser.
- Dumb by design. The executor doesn't know what a "test" is. It executes HTTP requests and returns results. All orchestration, comparison, and analysis stays in the platform. Less logic inside your perimeter means less to audit.
- Heartbeats and status. The platform tracks executor health (online/offline, last heartbeat, version), so a silent failure is visible immediately.
What a job looks like
Because the executor is a plain HTTP client, a job is easy to reason about. The shape below is illustrative, not a documented wire format, but it captures everything the executor needs to know:
// Illustrative only: a batch of requests handed to an executor
{
"jobId": "job_7f3a",
"requests": [
{
"method": "GET",
"url": "https://staging.internal.example/api/v2/products/sku-8841",
"headers": { "Accept": "application/json", "X-Market": "DE" }
},
{
"method": "POST",
"url": "https://staging.internal.example/api/v2/cart",
"headers": { "Content-Type": "application/json" },
"body": "{\"sku\":\"sku-8841\",\"qty\":1}"
}
]
}
The executor runs each request, records status, headers, body and timing, and sends that back. It doesn't evaluate assertions, store baselines or decide whether something regressed. That happens in the platform, where the snapshot, compare and assess workflow turns raw responses into classified diffs.
Scoping: who gets to use which executor
In practice, one executor is never enough, and "everyone shares one tunnel" is how test runs end up hitting the wrong environment. Executors should be scoped:
| Scope | Typical use |
|---|---|
| Organization | A shared executor in the corporate network that any team can route jobs through. |
| Brand / project | An executor colocated with a specific brand's staging stack. |
| User | A personal executor on a developer's laptop for testing services running locally. |
The routing rule is simple: most specific wins. A developer with a personal executor tests against localhost; everyone else falls through to the brand or organization executor.
The resolution logic, written as pseudocode, is short enough to explain in a design review:
// Pseudocode: which executor runs a job?
executor =
userExecutor(currentUser) if online
?? brandExecutor(job.brand) if online
?? orgExecutor(job.organization) if online
?? none // report clearly instead of silently running from the cloud
Two practical consequences follow. First, a brand team can run its own executor next to its staging stack without asking the platform team for anything. Second, a developer can point a full regression suite at a service running on their own machine before they open a pull request, then let the brand executor take over once the change lands in staging.
Where to run the executor
Because it's stateless and only needs outbound HTTPS, the executor can live almost anywhere that can reach the APIs you want to test. Common placements:
- A small VM or container in the same network segment as staging. The most common choice for a brand-scoped executor. Low latency to the APIs, so timing metrics stay meaningful.
- A pod in your Kubernetes cluster. Useful when the services under test are only reachable through cluster-internal DNS. Run it in the namespace (or with the network policy) that reflects what it is allowed to reach.
- A self-hosted CI runner. Many teams already have runners inside the network. Running the executor alongside them pairs naturally with a regression gate in the CI/CD pipeline: the pipeline triggers the comparison, the executor runs the requests, and the pipeline reads the verdict.
- A developer laptop. User-scoped, for local development and debugging. Turn it off and jobs fall through to the brand or org executor.
One rule of thumb: place the executor where your clients are. If your storefront calls the pricing service from inside the cluster, test it from inside the cluster too. A response measured from a different network path can differ in headers, caching and timing for reasons that have nothing to do with a regression.
A security review checklist for remote executors
Bring this list to the meeting with your security team. These are the questions that come up, and the answers the executor model is designed to give:
| Question | What to confirm |
|---|---|
| Does anything listen for inbound connections? | No. The executor only initiates outbound HTTPS. No firewall rule, port forward or tunnel is required. |
| How does it authenticate? | With a scoped API key. Keys are hashed (SHA-256) on the platform side, never stored in plaintext. Revoke the key and the executor stops getting jobs. |
| What can it reach? | Whatever its host can reach. Constrain it with the network controls you already use: segment, security group, network policy. |
| What logic runs inside the perimeter? | Only HTTP execution. No scripts from the platform, no test logic, no comparison engine. |
| What data leaves the network? | The responses to the requests it was asked to run, sent back over HTTPS so they can be compared to the baseline. Decide which environments and endpoints you test with that in mind. |
| How do we know it is healthy? | Heartbeats: online/offline status, last heartbeat and version are visible in the platform. |
The fifth row deserves a real conversation, not a checkbox. Pointing an executor at production systems that return personal data means that data is part of the response. Most teams solve this by testing staging and pre-production with synthetic data, which is far easier when that data is managed properly. Our guide to test data management for e-commerce QA covers how to give every environment realistic customers, addresses and payment cards without copying production.
What this unlocks
Once executors are in place, the distinction between "internal API" and "public API" disappears from your test strategy. The same regression suite, the same baselines, the same dashboards cover both - including the pre-production environments where regressions should be caught in the first place.
A few things change in day-to-day work:
- Staging becomes the main test target. Instead of finding a changed price field in production, you find it in staging the moment the deploy lands.
- Vendor upgrades get a safety net. When your commerce engine or CMS ships a new version into your private environment, you run a comparison against the baseline and see every changed response before customers do.
- GraphQL and REST are covered the same way. An executor doesn't care whether the request is a REST call or a GraphQL query, so query-based GraphQL regression testing works behind the firewall too.
- The security review happens once. After the executor model is approved, new teams and new environments reuse it instead of filing new firewall requests.
Getting started with API testing behind the firewall
A sensible rollout looks like this:
- Pick one environment that is currently untested because it isn't reachable (usually staging for one brand).
- Run a brand-scoped executor on a host in that network and confirm it shows as online.
- Take a baseline snapshot of the endpoints that matter most: product, price, cart, checkout.
- Run a comparison after the next deploy and review the diff with the team.
- Wire the comparison into the deploy pipeline once the noise rules are tuned.
APIpact ships this model natively: register an executor with an API key, and every snapshot or comparison can be routed through it. If your APIs live behind a firewall - which is to say, if you're an enterprise - book a walkthrough with your security team on the call and we'll go through the model in detail.
Frequently asked questions
How do you test APIs behind a firewall?
Run the test traffic from inside the network. You can host the whole test tool internally, open an inbound rule or VPN for a vendor, or run a small agent inside the network that connects out to the test platform. The agent approach (a remote executor) is the only one that needs no firewall change, because every connection is initiated from the inside over standard outbound HTTPS.
Can a SaaS tool test APIs that aren't exposed to the internet?
Yes, if the tool uses an agent inside your network that connects outward. A remote executor polls the platform over outbound HTTPS, runs requests against internal APIs locally and posts the results back, so no inbound access is needed.
Do I need to open firewall ports or set up a VPN to test internal APIs?
Not with the executor model. The executor only needs to make outbound HTTPS calls, the same as a browser on a workstation. Nothing listens for incoming connections, so there is no port to open and no tunnel to maintain.
Is a remote executor the same as a self-hosted test runner?
No. A self-hosted runner usually contains the test logic, assertions and reporting. A remote executor is a stateless HTTP client: it runs the requests it is given and returns raw responses. Baselines, comparison and analysis stay in the platform, which keeps the footprint inside your network small and easy to audit.
Can developers test services running on localhost?
Yes. A user-scoped executor on a developer's laptop takes priority for that user's jobs, so they can run the same regression suite against a local service. When the laptop executor is offline, jobs fall back to the brand or organization executor.
Bring your security team to the call.
The executor model is designed to survive a security review: outbound-only HTTPS, no inbound rules, no logic inside your perimeter. We'll walk your architects through it, hard questions welcome.
Discuss behind-firewall testing