The Incident
A startup founder came to me with a frustrating problem.
His e-commerce site worked perfectly on Wi-Fi. It worked on broadband. But the moment any of his customers opened it on Jio mobile data, they got a skeleton screen. No error message. No crash log. Just silence.
He had built the entire app using AI-generated code. Lovable, Bolt, ChatGPT, the whole vibe-coded stack. It looked great in demos. It worked fine on his laptop. But it was silently broken for a massive chunk of his actual user base.
Within an hour of looking at it, I had the root cause.
Supabase's API endpoints were being throttled or silently dropped by Jio's network at the ISP level. Not a bug in his code. Not a Vercel misconfiguration. A network-level routing problem completely invisible to anyone who doesn't understand what their stack is actually doing under the hood.
This Is Not Just a Supabase Problem
Before we get into the fix, let me give you the bigger picture because this will happen to you too if you are building apps for Indian users.
India has four major telecom providers that together serve over 1.1 billion mobile subscribers:
Jio (Reliance Jio): largest 4G/5G network in India, ~500 million subscribers
Airtel (Bharti Airtel): second largest, strong in urban and semi-urban areas
BSNL (Bharat Sanchar Nigam Limited): government-owned, widely used in rural and remote areas
Vi (Vodafone Idea): formed from the merger of Vodafone India and Idea Cellular
Each of these ISPs manages their own routing infrastructure, their own DNS resolvers, and their own peering agreements with international cloud providers. And they do not always behave the same way.
A site that loads instantly on Airtel may time out on Jio. A backend that works fine on BSNL may have degraded performance on Vi. This is not hypothetical. It happens regularly, it affects real businesses, and most developers building for Indian users have no idea it is a risk until it hits them in production.
Supabase themselves confirmed the Jio issue publicly:
Telling your users to install a VPN to use your app is not a solution. It is an acknowledgment that the infrastructure abstraction between your app and your vendor is broken. Here is how to fix it properly.
Step 1: Diagnose the Problem
Before touching any code, confirm the issue is ISP-level and not your own code.
Check global DNS resolution:
Go to whatsmydns.net and enter your backend URL. If it resolves fine everywhere but fails on specific mobile networks, it is ISP-level routing, not a code bug.
Test across networks:
Works on Wi-Fi, broken on Jio mobile data = ISP block
Broken everywhere = your code or your vendor
Check DevTools Network tab:
Open your app on an affected connection and look for:
net::ERR_CONNECTION_TIMED_OUT
net::ERR_NAME_NOT_RESOLVED
Either of these on your backend URLs means the ISP is the culprit.
Total time to fix: 5 hours. It would have been far less if the person who originally built the app had understood what they deployed.
Step 2: The Fix — Cloudflare Worker Reverse Proxy
The core idea: instead of your frontend calling your vendor URL directly (e.g. yourproject.supabase.co), it calls api.yourdomain.com which proxies the request through Cloudflare's global infrastructure. Indian ISPs do not block Cloudflare the same way they block direct connections to foreign cloud vendors.
2a. Create the Cloudflare Worker
Log into Cloudflare Dashboard, go to Workers and Pages, then Create Worker.
Replace the default code with:
export default {
async fetch(request, env) {
const url = new URL(request.url);
const SUPABASE_URL = "https://yourproject.supabase.co";
const targetURL = SUPABASE_URL + url.pathname + url.search;
const modifiedRequest = new Request(targetURL, {
method: request.method,
headers: request.headers,
body: request.method !== "GET" && request.method !== "HEAD"
? request.body
: null,
redirect: "follow",
});
return fetch(modifiedRequest);
},
};
Replace yourproject.supabase.co with your actual project URL and deploy.
2b. Add DNS Records
In Cloudflare Dashboard, go to your domain, then DNS, then Records, and add both:
2c. Add Worker Route
Go to Workers and Pages, then your Worker, then Settings, then Triggers, then Add Route:
api.yourdomain.com/*
Select your domain zone and save.
2d. Split Your Environment Variables
.env.production:
VITE_SUPABASE_URL=https://api.yourdomain.com
VITE_SUPABASE_ANON_KEY=your_anon_key
.env.development:
VITE_SUPABASE_URL=https://yourproject.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_key
Local dev hits Supabase directly. Production routes through Cloudflare. Clean separation with no DNS dependency for local development.
2e. Verify
After DNS propagates (usually 15 to 60 minutes), open:
https://api.yourdomain.com/rest/v1/
You should see a Supabase-style JSON response. That means the proxy is working and your Indian ISP users are now routing through Cloudflare instead of hitting the blocked endpoint directly.
Step 3: Build Defensively Going Forward
The Supabase-Jio incident is one specific case. The underlying vulnerability is architectural. Here are the practices that would have prevented this entirely.
Never expose third-party vendor URLs directly to users
If your frontend calls yourproject.supabase.co directly, you have zero control when that URL gets blocked, rate-limited, or the vendor changes their infrastructure.
Fragile:
VITE_API_URL=https://yourproject.supabase.co
Resilient:
VITE_API_URL=https://api.yourdomain.com
Now if you ever migrate away from Supabase, you update one DNS record instead of every line of frontend code.
Test on multiple Indian ISPs before launch
Before any production launch targeting Indian users, test on at least Jio and Airtel. They behave differently at the network level. A site that works perfectly on your Airtel broadband may be completely broken for 500 million Jio users. This takes 10 minutes and can prevent a production fire.
Add error boundaries to your frontend
A single failed API call should never white-screen your entire app. One network hiccup at the ISP level should show a graceful error, not kill the entire user session.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <div>Something went wrong. Please try again.</div>;
}
return this.props.children;
}
}
Wrap your app:
<ErrorBoundary>
<App />
</ErrorBoundary>
Monitor your proxy domain, not your vendor
Set up uptime monitoring on api.yourdomain.com using UptimeRobot (free tier available). Monitor your own domain, not yourproject.supabase.co. You want to know the moment your proxy goes down before your users do.
Keep client infrastructure on the client's account
If you are a freelancer or agency, never run client production infrastructure on your personal Cloudflare, AWS, or Vercel accounts. If payment disputes or billing issues arise, you end up either subsidizing their infrastructure or pulling the plug and breaking their live site. Transfer ownership before going live, every time.
TL;DR
The Jio-Supabase block will eventually be resolved. But the next ISP routing issue, the next vendor outage, the next DNS misconfiguration, those are coming regardless. The apps that survive them are the ones built with an abstraction layer between their frontend and their vendors.
One DNS record should never be able to take your entire app offline.
Final Thought
The founder genuinely believed I had just changed a link. That is the real cost of shipping code you do not understand. Not the bug itself, bugs are inevitable. But the inability to even know where to start looking when something breaks at the network level.
Vibe coding is a valid way to move fast. But understanding what you ship is not optional.
Building apps for Indian users or dealing with ISP-level issues? Drop a comment or connect with me, happy to help.
Inspired by a real incident I wrote about on LinkedIn. Read the story behind this fix here.



Top comments (3)
This post was inspired by a real client situation I shared on LinkedIn. If you want the story behind the fix, check it out here:
linkedin.com/posts/romanch11_webde...
Great explanation!!
Insightful!