One Cloudflare Worker Saved My Client's App When Supabase Got Blocked. It Also Cut TTFB in Half.
Your app works on your machine. It works on your phone. Then a user on a different ISP opens it and gets a blank screen, and you have no idea why because...
Garvit Sharma
20 June 2026 · 6 MIN READ
One Cloudflare Worker Saved My Client's App When Supabase Got Blocked. It Also Cut TTFB in Half.
webight.comOn this page
Your app works on your machine. It works on your phone. Then a user on a different ISP opens it and gets a blank screen, and you have no idea why because nothing in your code changed.
That happened to me in March 2026. A production app I built was live, paying, fine. Then users on Jio started messaging that login was broken. The app loaded, the buttons clicked, but every request to the backend just died. No error I could reproduce, because on my network everything was perfect.
The reason: Jio had started DNS-blocking *.supabase.co across India. Supabase is what the whole app runs on. 46 tables, 27 edge functions, Google OAuth, Razorpay payments. All of it talks to a something.supabase.co URL. And one carrier decided to stop resolving that domain.
So a chunk of the country couldn't reach the backend. The app wasn't down. The backend wasn't down. The road between them was closed.
The thing nobody tells you about your backend URL
See, when you build on a managed backend, you accept their domain without thinking. xyz.supabase.co. xyz.firebaseio.com. Whatever it is. Your frontend hardcodes it, your SDK hardcodes it, and you move on because it works.
But that domain is now a single point of failure you do not control. You can't change its DNS. You can't move it behind a CDN. You can't do anything if an ISP decides to block it, and ISPs in India block things for reasons that have nothing to do with you. The block hit a wildcard, so every Supabase project in the country was collateral.
I had no warning and no fix on the provider side. Supabase couldn't un-block themselves from Jio's resolver. The only move was to stop depending on a domain I didn't own.
What I actually did, in 2 hours
The plan was simple once I framed it right. Put a domain I control in front of Supabase. Route every backend call through that domain. Have it forward to Supabase server-side, where Jio's DNS block doesn't apply, because the block is on the user's resolver, not on Cloudflare's.
A Cloudflare Worker on a subdomain of the client's own domain. api.theirdomain.com. The Worker takes the request, rewrites the host, forwards it to the real Supabase URL, and streams the response back. The user's browser only ever sees api.theirdomain.com, which resolves fine on every carrier.
Here is the whole Worker. This is the real thing, not a sketch.
// worker.js: Supabase proxy on a domain you own
const SUPABASE_HOST = "yourproject.supabase.co";
export default {
async fetch(request) {
const url = new URL(request.url);
// Point the request at the real Supabase host
url.host = SUPABASE_HOST;
url.protocol = "https:";
url.port = "";
// Clone the request so we can rewrite the Host header
const headers = new Headers(request.headers);
headers.set("Host", SUPABASE_HOST);
const proxied = new Request(url.toString(), {
method: request.method,
headers,
body: request.method === "GET" || request.method === "HEAD"
? undefined
: request.body,
redirect: "manual",
});
const response = await fetch(proxied);
// Pass the response straight back, headers intact
const out = new Headers(response.headers);
out.set("Access-Control-Allow-Origin", "*");
out.set("Access-Control-Allow-Headers", "authorization, apikey, content-type, x-client-info");
out.set("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
if (request.method === "OPTIONS") {
return new Response(null, { status: 204, headers: out });
}
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: out,
});
},
};
Then in the app, the client config changes one line. The Supabase JS client takes a custom URL.
import { createClient } from "@supabase/supabase-js";
// Before: const url = "https://yourproject.supabase.co";
const url = "https://api.theirdomain.com"; // the Worker
export const supabase = createClient(url, ANON_KEY, {
auth: {
flowType: "pkce",
detectSessionInUrl: true,
},
});
The REST calls, the edge function calls, the realtime, all of it started flowing through the Worker. Jio users got the app back. Total cost: 0 rupees, because Cloudflare's free Worker tier covers far more requests than this app does in a day.
The one part that bit me: Google OAuth
REST and edge functions proxy cleanly. OAuth did not, and this is the part people skip in tutorials.
The default Supabase Google login uses a redirect flow. The browser sends the user to Google, Google sends them back to a callback that lives on supabase.co directly. That callback URL is baked into the OAuth flow, and it hits the blocked domain in the browser, where the block is active. So login still broke even after the proxy was up.
The fix was to switch Google to the ID-token flow. The browser gets the Google credential client-side using Google's own SDK, then hands that token to Supabase through the proxied domain. Google's domain isn't blocked. The token exchange goes through api.theirdomain.com. Nothing in the auth path touches supabase.co from the browser anymore.
// Load Google Identity Services, then:
function handleCredentialResponse(response) {
supabase.auth.signInWithIdToken({
provider: "google",
token: response.credential, // the JWT from Google
});
}
window.google.accounts.id.initialize({
client_id: GOOGLE_CLIENT_ID,
callback: handleCredentialResponse,
});
window.google.accounts.id.prompt();
That closed the last hole. Full app, including payments and login, running on a domain the client owns, end to end.
The part I didn't expect: it got faster
Here is the lesson I didn't go looking for. After the proxy was live, I checked TTFB out of habit. It had dropped to roughly half of what it was before.
The reason makes sense once you see it. A direct call from an Indian user to supabase.co does a fresh DNS lookup, a fresh TLS handshake, and then travels to wherever that Supabase region sits. Through the Worker, the user connects to the nearest Cloudflare edge, which is a few milliseconds away in most Indian cities. Cloudflare holds a warm connection to Supabase and reuses it. The slow first-byte cost of setting up the connection happens once on Cloudflare's side, not on every cold user request.
The first request from a Jio user used to take around 940ms to first byte. After the proxy, repeated requests from the same region settled near 460ms.
So the domain you put in front of your backend isn't only a resilience decision. It changes how close the connection setup happens to your user, and connection setup is most of what TTFB is for a cold visit. There's an SEO angle here too. Google's Core Web Vitals lean on how fast that first byte arrives, especially on mobile, and a faster TTFB feeds directly into LCP. The same move that kept the app alive also helped its rankings.
Why this is worth doing before you get blocked
Most people add a proxy after something breaks. I did too, under pressure, in 2 hours. It worked, but it was reactive.
The real takeaway is to own the layer between your app and your backend from day one. One Worker, one subdomain on a domain you already control, sitting in front of whatever managed service you use. It costs nothing on the free tier. It gives you a place to swap backends, add caching, block abuse, and survive the day an ISP decides your provider's domain is on a list.
For example, if I ever move that app off Supabase, the frontend doesn't change at all. It still calls api.theirdomain.com. I change where the Worker forwards. The 46 tables can become 46 tables somewhere else and not a single client device knows.
That's the difference between depending on a domain and owning one. The block taught me that the hard way. The speed bump was the bonus.
So go look at your own app right now. Find every place it calls a domain you don't own, a .supabase.co, a .firebaseio.com, an API host you can't move. That's your weak bridge. Put a Worker in front of it this week, while nothing is on fire, instead of the morning a carrier decides for you.
We build custom platforms, websites, and automation.
The two people who build it are the two you talk to, and every price is on the page.

Garvit Sharma
Full-stack developer and co-founder of Webight, a two-person web and AI studio in India. He writes these from real client work. More about us.
Keep reading
// RELATEDA Client Paid 3 Agencies for SEO Before Me. None of Them Opened the Website Code.
webight.comA Client Paid 3 Agencies for SEO Before Me. None of Them Opened the Website Code.
7 MIN READ
The Contact Form Setup That Stopped Landing in Spam. Resend, Next.js, DKIM.
webight.comThe Contact Form Setup That Stopped Landing in Spam. Resend, Next.js, DKIM.
6 MIN READ
Claude Code Fixed 6 SEO Bugs on My Site in 40 Minutes. The Exact Prompts.
webight.comClaude Code Fixed 6 SEO Bugs on My Site in 40 Minutes. The Exact Prompts.
8 MIN READ