QuotaGuard and Netlify Integration Guide

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:

  1. Go to your site’s Site configuration
  2. Navigate to Functions settings
  3. 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:

  1. Go to your site’s Site configuration
  2. Navigate to Environment variables
  3. Click Add a variable
  4. Key: QUOTAGUARDSTATIC_URL
  5. Value: Your proxy URL from the QuotaGuard dashboard
  6. 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:

  1. Have the Edge Function call a Netlify Serverless Function
  2. The Serverless Function makes the proxied external API call
  3. 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:

  1. Connection must open, execute, and close within Netlify’s timeout limits (10 seconds default, 26 seconds max for synchronous functions)
  2. Connection pooling is not possible between invocations
  3. Cold starts add additional latency

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:

  1. Traffic routes through QuotaGuard’s infrastructure instead of the nearest edge
  2. 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:

  1. The environment variable is set correctly:
    netlify env:list
    
  2. The URL format includes credentials:
    http://username:password@us-east-static-01.quotaguard.com:9293
    
  3. Check for special characters in your password that may need URL encoding.

Connection Timeout

  1. Verify the QuotaGuard proxy hostname is correct (check your dashboard)
  2. Ensure port 9293 is used for HTTP proxy connections
  3. Check if the target service is reachable from QuotaGuard’s infrastructure
  4. Increase function timeout in netlify.toml if needed:
[functions]
  node_bundler = "esbuild"

[functions."your-function-name"]
  timeout = 26

Wrong IP Address Returned

If ip.quotaguard.com returns an unexpected IP:

  1. Verify the proxy agent is being passed to the fetch call
  2. Check that you’re not accidentally using a non-proxied fetch
  3. 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

  1. Verify the variable scope includes “Functions” in the Netlify UI
  2. Environment variables set via CLI may take a few minutes to propagate
  3. 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.

Try QuotaGuard Now

View Netlify Integration Features

Contact Support


Ready to Get Started?

Get in touch or create a free trial account

Back to top ↑

Copyright © 2009 - 2026 QuotaGuard. All rights reserved.