Skip to content
Fixedmark
Integration · Serverless and edge functions

Supabase Edge Functions Static IP (Deno Proxy)

Supabase Edge Functions have no static outbound IP, and Supabase's own docs recommend an outbound proxy. The IPv4 add-on gives your database an inbound address, not your functions an outbound one. Edge Functions run on Deno, so you can pass a Fixedmark proxy to `fetch` with `Deno.createHttpClient` and allowlist a dedicated IP pair.

Why Supabase Edge Functions have no fixed IP

Edge Functions run in isolates distributed across Supabase's infrastructure, close to your users or your database. The outbound address depends on where the isolate runs, and Supabase does not publish a fixed egress list for functions.

Apps built with Lovable use Supabase Edge Functions for server-side calls, so they hit the same wall when a payment gateway, CRM, or customer API demands a fixed source IP.

Supabase's native options

Supabase has no static egress product for Edge Functions. Its troubleshooting guide says so and suggests routing calls through an outbound proxy you control. The dedicated IPv4 add-on is often mistaken for a fix. Per Supabase's docs, it costs about $4 per month on Pro and above and gives your database an IPv4 address for incoming connections. The docs state the outbound IP is not static.

That makes a proxy the only route today. Deno's fetch accepts a custom HTTP client with a proxy, which is the mechanism shown below. The Supabase Edge Runtime exposes Deno.createHttpClient from release 1.68.

Sources for Supabase Edge Functions pricing

Checked October 2026. Confirm current details on the vendor's site before you decide. Prices and limits change.

Set up a static IP on Supabase Edge Functions

You create one proxied client per function and pass it to the fetch calls that need the fixed IP.

Fixedmark is in early access. Proxy URLs are issued at launch. Join early access to get yours when your region opens.

Before you start

  • A Supabase project and the Supabase CLI, logged in and linked (supabase link).
  • A Fixedmark proxy URL (https://APP_ID:TOKEN@mum.egress.fixedmark.com:443) and the two IPs of your pair. Both are issued at launch. Join early access to get them.
  • Access to the partner's or database's allowlist, or a contact who can add two IPv4 addresses for you.

Steps

  1. 1
    Store the proxy URL as a function secretRun supabase secrets set FIXEDMARK_PROXY_URL=https://APP_ID:TOKEN@mum.egress.fixedmark.com:443, or add it under Edge Functions, Secrets in the dashboard. Secrets are available to every function through Deno.env.get without a redeploy.
  2. 2
    Create the proxied client at module scopeCall Deno.createHttpClient({ proxy: { url, basicAuth } }) once, outside Deno.serve, so the isolate reuses it across requests.
  3. 3
    Pass the client to fetchAdd client to the fetch options for the allowlisted calls. Calls to Supabase itself (database, storage, auth) stay direct.
  4. 4
    Deploy, verify, and allowlist both IPsRun supabase functions deploy partner-orders. Deploy the IP check function below once, invoke it, then give the partner both IPs from your Fixedmark pair.
// supabase/functions/partner-orders/index.ts
const proxy = new URL(Deno.env.get("FIXEDMARK_PROXY_URL")!);

// Create the client once per isolate, not per request.
const client = Deno.createHttpClient({
  proxy: {
    url: `${proxy.protocol}//${proxy.host}`,
    basicAuth: {
      username: decodeURIComponent(proxy.username),
      password: decodeURIComponent(proxy.password),
    },
  },
});

Deno.serve(async () => {
  const res = await fetch("https://api.partner.example/v1/orders", {
    client,
    headers: { authorization: `Bearer ${Deno.env.get("PARTNER_API_KEY")}` },
  });
  return new Response(await res.text(), { status: res.status });
});

The snippet passes credentials as basicAuth rather than inside the proxy URL, which is the form Deno documents. We tested this code on Deno 2 against an https:// proxy. We are still confirming that the hosted Supabase Edge Runtime allows the proxy option on every release, so run the IP check before you send the IPs to a partner.

Verify the egress IP on Supabase

Check the IP before you send it to a partner. Deploy the check below as its own function and invoke it with supabase functions invoke egress-check or curl. It returns both the proxied IP and the function's own IP. The endpoint https://fixedmark.com/api/ip returns the caller's IP as plain text, and the What's my IP tool shows the same thing in a browser.

The proxied call should print one of your two Fixedmark IPs every time. The direct call should print a different address. If both print the same platform IP, the client is not using the proxy.

// supabase/functions/egress-check/index.ts
// Deploy, invoke once, then delete the function.
const proxy = new URL(Deno.env.get("FIXEDMARK_PROXY_URL")!);
const client = Deno.createHttpClient({
  proxy: {
    url: `${proxy.protocol}//${proxy.host}`,
    basicAuth: {
      username: decodeURIComponent(proxy.username),
      password: decodeURIComponent(proxy.password),
    },
  },
});

Deno.serve(async () => {
  const via = await fetch("https://fixedmark.com/api/ip", { client });
  const direct = await fetch("https://fixedmark.com/api/ip");
  return Response.json({
    fixedmark: (await via.text()).trim(),
    platform: (await direct.text()).trim(),
  });
});

Databases from Edge Functions

Your Supabase database does not need any of this. Functions reach it over Supabase's network and the client libraries.

For an external IP-restricted database, Deno's Postgres and MongoDB drivers have no SOCKS5 option, and Edge Functions cannot run bm tunnel. Call the external database through an HTTP API via the proxied client, or move that query into a small service on a platform that can run the tunnel. See Postgres and MySQL allowlists.

Common errors and fixes

Deno.createHttpClient is not a function

Older Supabase Edge Runtime versions did not expose it. Update the Supabase CLI for local serving. On hosted projects, tell us during early access so we can track the runtime version.

Deno.env.get returns undefined for the secret

Secret names are case sensitive. Run supabase secrets list to check it exists in the linked project. Local supabase functions serve reads supabase/functions/.env, not hosted secrets.

407 Proxy Authentication Required

The proxy did not get valid credentials. Check that the env var holds the full URL with APP_ID:TOKEN@, with no quotes or trailing newline. If the token contains @, :, or /, URL-encode it. Some clients drop credentials from the URL: pass them separately (Deno's basicAuth, axios proxy.auth) or switch to undici's ProxyAgent, which reads them from the URL.

TLS errors to the proxy: wrong version number, EPROTO, Proxy CONNECT aborted, or unable to connect to proxy

The client does not support an https:// proxy URL and is speaking plain HTTP to port 443. Upgrade it: curl 7.52+, urllib3 1.26+ (requests), httpx 0.26+, undici ProxyAgent, Go 1.10+. In Ruby, use Typhoeus: Net::HTTP and Faraday's default adapter cannot tunnel HTTPS through a TLS proxy. For older axios releases, set proxy: false and pass https-proxy-agent as httpsAgent. Java's built-in HttpClient cannot speak TLS to a proxy at all. If you cannot upgrade, use the SOCKS5 URL.

ETIMEDOUT or ECONNRESET to the partner, or a 403 from the partner

The proxy connected, but the destination dropped you. Usually only one IP of the pair is on the allowlist, or the partner has not applied the change yet. Add both IPs. If a destination allowlist is set on your Fixedmark token, check the host and port are on it.

The IP check prints the platform's IP, not a Fixedmark IP

The request went direct. Node's built-in fetch ignores HTTPS_PROXY unless NODE_USE_ENV_PROXY=1 is set (Node 22.21+ and 24+). Many SDKs ignore proxy env vars too. Pass the proxy to the client explicitly, as in the snippets above.

429 or 407 with an X-Proxy-Error: quota_exceeded header

Planned behavior when you pass your plan's soft limit. Check usage in the dashboard or raise the plan.

Database driver has no proxy option

node-postgres, mysql2, psycopg, and most ORMs cannot use an HTTP proxy. Use a SOCKS5-capable driver with FIXEDMARK_SOCKS_URL, or run bm tunnel where the platform allows a second process.

Gotchas on Supabase

Deno's proxy client applies to fetch only. WebSocket connections and raw TCP from Deno.connect do not go through it.

  • Do not rely on HTTPS_PROXY in Edge Functions. Pass the client explicitly so only allowlisted calls use the proxy.
  • Function regions and Fixedmark regions do not always match. Pick the Fixedmark region nearest the partner API if functions run in many places.
  • Keep the secret out of the browser. Never read it from client-side code in a Lovable or Next.js app.
  • Outbound ports 25 and 587 are blocked on Edge Functions, through the proxy or not.

Frequently asked questions

Do Supabase Edge Functions have a static IP?

No. Supabase does not offer static egress IPs for Edge Functions and recommends routing outbound calls through a proxy. A static IP proxy gives those calls a fixed source address.

Does the Supabase IPv4 add-on give Edge Functions a static IP?

No. Per Supabase's docs, the IPv4 add-on gives your database an IPv4 address for incoming connections. It does not change the outbound IP of Edge Functions.

How do I set a proxy for fetch in a Supabase Edge Function?

Create a client with Deno.createHttpClient({ proxy: { url, basicAuth } }) and pass it as the client option to fetch. Store the proxy URL as a function secret and read it with Deno.env.get.

Does this work for Lovable apps?

Yes. Lovable's backend runs on Supabase Edge Functions, so the same secret and client code apply. Put the proxied fetch in the edge function, never in browser code.

Can Edge Functions connect to an external Postgres through the static IP?

Not directly at launch. Deno's database drivers have no SOCKS5 option and functions cannot run a tunnel process. Use an HTTP API or a small relay service on another platform.

Fix your egress IP.

Fixedmark is in early access. Join the list to get a dedicated IP pair for Supabase Edge Functions when your region opens.