QuotaGuard and Netlify Integration Guide
Table of contents
- QuotaGuard and Netlify Integration Guide
- Why Netlify Functions Need Static IPs
- Native Private Connectivity vs QuotaGuard
- Getting Started
- Configuring Netlify Functions (Node.js)
- Configuring Netlify Edge Functions (Deno)
- Database Connections (SOCKS5)
- Testing Your Implementation
- Latency Considerations
- Troubleshooting
- Common Use Cases
- QuotaGuard Static vs QuotaGuard Shield
- Ready to Get Started?
QuotaGuard and Netlify Integration Guide
QuotaGuard Static IPs allow your Netlify Functions to send outbound traffic through a load-balanced pair of static IP addresses. Once set up, you can use QuotaGuard’s IPs to connect to firewalled databases and APIs that require IP allowlisting.
Netlify offers two serverless compute options:
| Function Type | Runtime | Best For |
|---|---|---|
| Netlify Functions | Node.js 18+ | Backend logic, API calls, database connections |
| Netlify Edge Functions | Deno | Low-latency personalization, A/B testing, geolocation |
This guide focuses on Netlify Functions (Node.js) as the recommended option for proxy usage. Edge Functions have known limitations with proxy configuration that we’ll address separately.
You do not need QuotaGuard for internal Netlify operations. QuotaGuard is for connecting to external services that require a known, static source IP address.
Why Netlify Functions Need Static IPs
Netlify’s infrastructure uses dynamic, rotating IP addresses from AWS and Google Cloud pools. The platform explicitly states they do not publish outbound IP ranges because these addresses can change without notice.
This creates problems when your functions need to connect to:
- Payment providers like Line Pay, PayPal, or Stripe Connect that require IP whitelisting
- MongoDB Atlas or other databases with IP-based network access controls
- Azure SQL and Amazon RDS security groups
- Google Workspace with Context-Aware Access policies
- Enterprise firewalls that block unknown cloud IP ranges
- Partner APIs with strict access controls
The result is connection failures and 403 Forbidden errors that have nothing to do with your code. Your API keys are valid. Your function logic is correct. The target service is simply blocking requests from Netlify’s dynamic IP addresses.
QuotaGuard gives your Netlify Functions a fixed, verifiable identity that partners can add to their firewall allowlists once.
Native Private Connectivity vs QuotaGuard
Netlify offers a Private Connectivity feature for static egress IPs. Here’s how it compares to QuotaGuard:
| Feature | Netlify Private Connectivity | QuotaGuard |
|---|---|---|
| Plan requirement | Enterprise only | Any plan |
| Setup process | Contact account manager | Self-service |
| Serverless Functions support | Yes (limited regions) | Yes (all regions) |
| Edge Functions support | No | Yes (with caveats) |
| Regions available | us-east-2, eu-central-1, eu-west-2 only | 10+ global regions |
| IP allocation | Multiple IPs per region | Dedicated pair per account |
| Add-ons required | High-Performance Edge or Build | None |
Use Private Connectivity if you’re on an Enterprise plan, only need Serverless Functions, and your target services are in supported regions.
Use QuotaGuard if you’re on a free, pro, or business plan. Or if you need Edge Functions support, more regional options, or immediate self-service setup.
Getting Started
After creating a QuotaGuard account, you will be redirected to your dashboard where you can find your proxy credentials and static IP addresses.
Choose the right proxy region: Netlify Functions run in a specific AWS region (configurable in site settings). Match your QuotaGuard region to minimize latency.
| Netlify Functions Region | QuotaGuard Region |
|---|---|
| us-east-1 (default) | US-East |
| us-east-2 | US-East |
| eu-central-1 | EU-Central (Frankfurt) |
| ap-southeast-1 | AP-Southeast (Singapore) |
| ap-southeast-2 | Australia (Sydney) |
To check or change your Netlify Functions region:
- Go to your site’s Site configuration
- Navigate to Functions settings
- Look for Region setting
Your QuotaGuard proxy URL looks like this:
http://username:password@us-east-static-01.quotaguard.com:9293
Finding Your Static IPs: Your two static IPs are displayed in the QuotaGuard dashboard. Both IPs are active simultaneously for high availability. Add both to any firewall allowlists you’re configuring on the target service side.
Configuring Netlify Functions (Node.js)
Netlify Functions use Node.js 18+ which includes native fetch. However, native fetch requires a proxy agent for routing through QuotaGuard.
Step 1: Add Your Proxy URL as an Environment Variable
Using Netlify CLI:
netlify env:set QUOTAGUARDSTATIC_URL "http://username:password@us-east-static-01.quotaguard.com:9293"
Using Netlify UI:
- Go to your site’s Site configuration
- Navigate to Environment variables
- Click Add a variable
- Key:
QUOTAGUARDSTATIC_URL - Value: Your proxy URL from the QuotaGuard dashboard
- Scopes: Ensure Functions is selected
Important: Netlify does not read .env files during builds. You must set environment variables through the CLI or UI.
Step 2: Install the Proxy Agent
Add the https-proxy-agent package to your project:
npm install https-proxy-agent
Or with yarn:
yarn add https-proxy-agent
Step 3: Configure Your Function
Create your function in the netlify/functions/ directory.
Basic GET Request
// netlify/functions/api-call.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
if (!proxyUrl) {
return new Response(
JSON.stringify({ error: 'Proxy URL not configured' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
const agent = new HttpsProxyAgent(proxyUrl);
try {
const response = await fetch('https://api.example.com/data', {
agent: agent
});
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
};
POST Request with JSON Body
// netlify/functions/submit-data.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
// Parse incoming request body
const payload = await req.json();
try {
const response = await fetch('https://api.example.com/submit', {
method: 'POST',
agent: agent,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.API_TOKEN}`
},
body: JSON.stringify(payload)
});
const result = await response.json();
return new Response(JSON.stringify(result), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
};
Error Handling Pattern
// netlify/functions/robust-api-call.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
if (!proxyUrl) {
console.error('QUOTAGUARDSTATIC_URL not configured');
return new Response(
JSON.stringify({ error: 'Proxy configuration missing' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
const agent = new HttpsProxyAgent(proxyUrl);
try {
const response = await fetch('https://api.example.com/data', {
agent: agent,
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`
}
});
if (!response.ok) {
console.error(`API returned ${response.status}: ${await response.text()}`);
return new Response(
JSON.stringify({ error: `Upstream API error: ${response.status}` }),
{ status: response.status, headers: { 'Content-Type': 'application/json' } }
);
}
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
console.error('Request failed:', error);
if (error.message.includes('407')) {
return new Response(
JSON.stringify({ error: 'Proxy authentication failed' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
return new Response(
JSON.stringify({ error: 'Request failed' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
};
Background Function Example
For long-running operations, use Netlify’s background functions (append -background to the filename):
// netlify/functions/sync-data-background.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
// This runs for up to 15 minutes instead of 10 seconds
const records = await fetchAllRecords();
for (const record of records) {
await fetch('https://partner-api.example.com/sync', {
method: 'POST',
agent: agent,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(record)
});
}
console.log(`Synced ${records.length} records`);
};
Using Axios Instead of Fetch
If you prefer axios:
// netlify/functions/axios-example.mjs
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
try {
const response = await axios.get('https://api.example.com/data', {
httpsAgent: agent,
headers: {
'Authorization': `Bearer ${process.env.API_KEY}`
}
});
return new Response(JSON.stringify(response.data), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
};
Install axios: npm install axios
Configuring Netlify Edge Functions (Deno)
Important: As of January 2026, there are known issues with Deno.createHttpClient in Netlify’s production Edge runtime. The Netlify team is investigating these issues. For production proxy use cases, we recommend using Netlify Functions (Node.js) instead.
If you need to experiment with Edge Functions proxy configuration:
// netlify/edge-functions/api-call.ts
export default async (req: Request, context: Context) => {
const proxyUrl = Deno.env.get('QUOTAGUARDSTATIC_URL');
if (!proxyUrl) {
return new Response(
JSON.stringify({ error: 'Proxy not configured' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
const url = new URL(proxyUrl);
// Note: Deno.createHttpClient may not work reliably in Netlify's Edge runtime
const client = Deno.createHttpClient({
proxy: {
url: `${url.protocol}//${url.host}`,
basicAuth: {
username: url.username,
password: url.password,
},
},
});
try {
const response = await fetch('https://api.example.com/data', { client });
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
} finally {
client.close();
}
};
Recommendation: If your Edge Function needs to call IP-restricted APIs, consider restructuring your application to:
- Have the Edge Function call a Netlify Serverless Function
- The Serverless Function makes the proxied external API call
- The result is returned through the Edge Function to the client
This adds latency but provides reliable proxy support.
Database Connections (SOCKS5)
For non-HTTP protocols like PostgreSQL, MySQL, or MongoDB native drivers, use QuotaGuard’s SOCKS5 proxy on port 1080.
Limitations in Netlify Functions
Netlify Functions are serverless and ephemeral. Each invocation starts fresh with no persistent connections. This creates challenges for database connections:
- Connection must open, execute, and close within Netlify’s timeout limits (10 seconds default, 26 seconds max for synchronous functions)
- Connection pooling is not possible between invocations
- Cold starts add additional latency
Recommended Approaches
Use HTTP/REST APIs when available:
Many databases offer HTTP APIs that work with the standard proxy configuration:
- MongoDB Atlas Data API
- Supabase REST API
- PlanetScale HTTP API
- Neon serverless driver
Example: MongoDB Atlas Data API
// netlify/functions/mongo-query.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
const query = {
dataSource: 'Cluster0',
database: 'mydb',
collection: 'users',
filter: { status: 'active' }
};
const response = await fetch(
'https://data.mongodb-api.com/app/data-xxxxx/endpoint/data/v1/action/find',
{
method: 'POST',
agent: agent,
headers: {
'Content-Type': 'application/json',
'api-key': process.env.MONGODB_API_KEY
},
body: JSON.stringify(query)
}
);
const result = await response.json();
return new Response(JSON.stringify(result.documents), {
headers: { 'Content-Type': 'application/json' }
});
};
For native database connections:
If you must use native database drivers with SOCKS5, consider using a longer-running compute option like Netlify’s background functions or a dedicated service on a platform that supports QGTunnel (Heroku, Render, Fly.io).
Testing Your Implementation
Local Testing with Netlify Dev
Test locally before deploying:
# Set the environment variable locally
netlify env:set QUOTAGUARDSTATIC_URL "http://username:password@us-east-static-01.quotaguard.com:9293" --context dev
# Start the local dev server
netlify dev
Then test your function at http://localhost:8888/.netlify/functions/your-function-name
Test Function to Verify Proxy
Create a simple test function:
// netlify/functions/test-proxy.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
if (!proxyUrl) {
return new Response(
JSON.stringify({ error: 'QUOTAGUARDSTATIC_URL not set' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
const agent = new HttpsProxyAgent(proxyUrl);
try {
// ip.quotaguard.com returns the client's IP address
const response = await fetch('https://ip.quotaguard.com', { agent });
const data = await response.json();
return new Response(
JSON.stringify({
your_static_ip: data.ip,
proxy_working: true
}),
{ headers: { 'Content-Type': 'application/json' } }
);
} catch (error) {
return new Response(
JSON.stringify({
error: error.message,
proxy_working: false
}),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
};
Deploy and invoke:
netlify deploy --prod
curl https://your-site.netlify.app/.netlify/functions/test-proxy
Expected response:
{
"your_static_ip": "52.34.188.175",
"proxy_working": true
}
The returned IP should match one of your two static IPs shown in the QuotaGuard dashboard. Run it multiple times to see both IPs in action (load-balanced).
Latency Considerations
Using QuotaGuard adds a network hop to your requests:
| Configuration | Added Latency |
|---|---|
| Same region (Netlify us-east-1 + QuotaGuard US-East) | 10-30ms |
| Cross-region | 50-100ms |
Selective Proxying
Only proxy requests that require static IPs. Keep non-firewalled API calls using standard fetch without the proxy:
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
// Non-proxied request to public API (faster)
const publicData = await fetch('https://api.publicservice.com/data');
// Proxied request to firewalled API (needs static IP)
const privateData = await fetch('https://partner.firewalled.com/secure', {
agent: agent
});
return new Response(JSON.stringify({
public: await publicData.json(),
private: await privateData.json()
}), {
headers: { 'Content-Type': 'application/json' }
});
};
Edge Functions Tradeoff
Edge Functions are designed for global low-latency execution. Adding a proxy may negate these benefits because:
- Traffic routes through QuotaGuard’s infrastructure instead of the nearest edge
- The proxy adds a network hop regardless of edge location
For latency-sensitive operations that also require static IPs, consider whether Serverless Functions in a single region might be more predictable than Edge Functions with a proxy.
Troubleshooting
407 Proxy Authentication Required
Your proxy credentials are incorrect. Verify:
- The environment variable is set correctly:
netlify env:list - The URL format includes credentials:
http://username:password@us-east-static-01.quotaguard.com:9293 - Check for special characters in your password that may need URL encoding.
Connection Timeout
- Verify the QuotaGuard proxy hostname is correct (check your dashboard)
- Ensure port 9293 is used for HTTP proxy connections
- Check if the target service is reachable from QuotaGuard’s infrastructure
- Increase function timeout in
netlify.tomlif needed:
[functions]
node_bundler = "esbuild"
[functions."your-function-name"]
timeout = 26
Wrong IP Address Returned
If ip.quotaguard.com returns an unexpected IP:
- Verify the proxy agent is being passed to the fetch call
- Check that you’re not accidentally using a non-proxied fetch
- Ensure the environment variable scope includes “Functions”
Edge Functions Proxy Not Working
This is a known limitation. As of January 2026, Deno.createHttpClient may not work reliably in Netlify’s production Edge runtime.
Solution: Use Netlify Serverless Functions (Node.js) instead of Edge Functions for proxy use cases.
Module Not Found: https-proxy-agent
Ensure the package is in your package.json dependencies (not devDependencies) and committed to your repository:
npm install https-proxy-agent --save
git add package.json package-lock.json
git commit -m "Add https-proxy-agent for QuotaGuard proxy"
Environment Variable Not Available
- Verify the variable scope includes “Functions” in the Netlify UI
- Environment variables set via CLI may take a few minutes to propagate
- Redeploy your site after adding new environment variables
Common Use Cases
Payment Provider Integrations
Payment APIs often require IP allowlisting for security:
// netlify/functions/process-payment.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
const payload = await req.json();
const response = await fetch('https://api.paymentprovider.com/v1/charges', {
method: 'POST',
agent: agent,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.PAYMENT_API_KEY}`
},
body: JSON.stringify({
amount: payload.amount,
currency: 'USD',
source: payload.token
})
});
const result = await response.json();
return new Response(JSON.stringify(result), {
headers: { 'Content-Type': 'application/json' }
});
};
Webhook Delivery to Firewalled Endpoints
When your function needs to deliver webhooks to systems with IP restrictions:
// netlify/functions/send-webhook.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
import crypto from 'crypto';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
const event = await req.json();
const signature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(JSON.stringify(event))
.digest('hex');
const response = await fetch('https://partner.example.com/webhooks/receive', {
method: 'POST',
agent: agent,
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': signature
},
body: JSON.stringify(event)
});
if (!response.ok) {
console.error(`Webhook delivery failed: ${response.status}`);
return new Response('Webhook delivery failed', { status: 500 });
}
return new Response('OK', { status: 200 });
};
Enterprise API Integration
Connecting to corporate APIs behind firewalls:
// netlify/functions/enterprise-sync.mjs
import { HttpsProxyAgent } from 'https-proxy-agent';
export default async (req, context) => {
const proxyUrl = process.env.QUOTAGUARDSTATIC_URL;
const agent = new HttpsProxyAgent(proxyUrl);
const response = await fetch('https://api.enterprise-partner.com/v2/data', {
agent: agent,
headers: {
'X-API-Key': process.env.ENTERPRISE_API_KEY,
'X-Client-ID': process.env.ENTERPRISE_CLIENT_ID
}
});
if (!response.ok) {
return new Response(
JSON.stringify({ error: `API error: ${response.status}` }),
{ status: response.status, headers: { 'Content-Type': 'application/json' } }
);
}
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
});
};
QuotaGuard Static vs QuotaGuard Shield
QuotaGuard offers two products for static IPs:
| Feature | QuotaGuard Static | QuotaGuard Shield |
|---|---|---|
| Protocol | HTTP/SOCKS5 | HTTPS/SOCKS5 over TLS |
| Encryption | Standard proxy | SSL Passthrough (E2EE) |
| Best for | General API access | HIPAA, PCI-DSS, regulated data |
| Starting price | $19/month | $69/month |
For most Netlify Functions, QuotaGuard Static provides everything you need. Choose Shield if you’re handling protected health information (PHI), payment card data, or have specific compliance requirements where even the proxy provider must not be able to inspect traffic.
Ready to Get Started?
Get in touch or create a free trial account.
View Netlify Integration Features