I spent a week migrating data. Beta started on 23rd February. By midnight, the app was dead.

Not a code error. Not a logic failure. My team could not log in. I opened my laptop and checked Cloudflare — no noise, no outage. Then I opened the Supabase status page.

Indian ISPs had blocked supabase.co. Every API call my app made routed directly to that domain. With the block in place, the app was unreachable without a VPN or DNS change. I had never put ISP block on my risk list. I had mapped compliance risks, schema failures, and data migration gaps. I had not mapped India’s ISPs. This was not a product failure. It was a single-vendor dependency failing at the network layer — the kind of risk that does not show up in your code review.

I checked Reddit and developer forums. The same complaint was widespread. Other Indian developers were hitting the same wall. Supabase acknowledged the issue. The community focused on raising complaints to ISPs. That was going to take days, maybe weeks. I needed a fix by morning.


Three Options, One I Could Trust

I had three ways out.

The first was upgrading to a paid Supabase plan at Rs 2,075 ($25) per month to enable a custom domain. It was the fastest option on paper. I rejected it for three reasons. My current setup was sufficient for beta. I did not know how the ISP had applied the block — if the custom domain resolved back to supabase.co at the DNS level, I would have paid Rs 2,075 to fix nothing. And if a different domain got blocked tomorrow, I would be back to the same problem with no fix that holds.

The second was switching all my staff devices to Cloudflare’s 1.1.1.1 DNS or Google’s 8.8.8.8. Impossible in practice. My supervisors and field staff are not sitting in an office. Asking thirty people spread across locations to change their DNS settings was not a morning fix.

The third option was rerouting all API calls through Cloudflare Workers. Instead of my app calling supabase.co directly, every request would go to Cloudflare first, which would then call Supabase and return the result.

This had one obvious risk. My app was already hosted on Cloudflare. If Cloudflare went down, my app was already down. The new architecture made me more dependent on Cloudflare, but my failure mode did not change. The downside was the same — the upside was a working app.


One Day, Not Three

I asked the AI to research the approach and present a clear plan before touching any code. It broke the migration into phases and built a working proxy for one API collection first. Small errors came up. I corrected them. Once that collection worked, the next two went faster. I deployed to Cloudflare and tested. It held. Over the next six hours, I migrated every API call.

The extra latency worried me. I tested it directly — the same API call, twice. Once through the Cloudflare proxy. Once directly to Supabase over VPN, bypassing the block. The difference between the two response times is the proxy overhead. It added between 22 and 40 milliseconds on average. My app’s data fetch times run between one and three seconds. Nobody notices 35 milliseconds inside a two-second load.

The request volume jumped. Pre-migration, 25 users generated 5,000 daily requests — roughly 200 per user per day. Post-migration, that jumped to 9,000. The Cloudflare proxy adds around 160 requests per user per day for supervisors. At 300 users with a realistic mix of heavy and light users, daily requests stay around 54,000 — within the 100,000 free tier limit. If I hit it, a Rs 415 ($5) per month plan handles ten million requests. Hitting the limit is a good problem. It means the app is working.

One thing could not be migrated. Google Sign-in uses Supabase’s own OAuth system, which connects to supabase.co directly. Rerouting it would mean building a custom OAuth server inside Cloudflare Workers and reworking the entire auth system. The feature was never critical. My team already used email sign-in. I dropped Google Sign-in and moved on.

By end of day, the app was running. Supabase keeps users logged in for fifteen days without a fresh login required. Anyone already logged in stayed logged in. Total downtime was 30 minutes on the night of 23rd February and three complaints after. The rest of the team noticed nothing.


What Documentation Actually Did

I had always used documentation as a reference system — not just for future migrations but to keep the AI working within my rules across sessions. Every new coding session starts with the same context: coding standards, data display rules, package choices, business goals. Without that, the AI starts fresh each time and makes its own choices. Documentation is how I keep it inside my system rather than inventing its own.

The one-day recovery did not happen because AI is fast. It happened because every function in O9X was commented. Every workflow was written down. Logic, inputs, outputs, error handling, and assumptions. Those are the five fields I force into every function comment. That is what gave the AI a clean specification to work from.

Without that documentation, the same fix costs roughly four to nine times my monthly AI spend. My current AI subscriptions run at around Rs 1,700 per month — Claude and Gemini combined. Under pressure, without context, AI burns tokens rebuilding what should already be known. At API rates, the same recovery session costs between Rs 8,000 and Rs 15,000. I did not build the documentation to protect me from an ISP block. I built it to keep my AI coding sessions consistent. It turned out to protect me from an event I never modelled.

My API keys already lived in Cloudflare Secrets — they were never exposed. The actual exposure was narrower than I had assumed. Client-side code runs in the browser. A determined user who managed to log in could inspect that code and find API call patterns not meant to be visible. For a high-value app, that is serious. For a 30-user internal operations tool where access requires authentication, I had parked it for after beta. The migration removed that surface anyway. Not because I planned it — rerouting through Cloudflare Workers made it inevitable.


Questions Operators Ask

Should I avoid Supabase if I am building for Indian users? Not necessarily. Supabase resolved the block within a week. The issue was external infrastructure — not a product failure. The right response is to make sure one external dependency cannot kill your entire app overnight. For me that was Cloudflare Workers. For others it could be any server-side proxy between your app and your database.

Does routing through Cloudflare Workers slow down my app? In my tests, the proxy added between 22 and 40 milliseconds of latency. Test your own setup with the two-call VPN comparison before assuming the overhead is a problem.

Is documentation worth the token cost during an AI build? I force every AI model to document each function — the logic, inputs, outputs, error handling, and assumptions. This uses between 10 and 20 percent of my token limits per session. Without it, returning to code two days later means reverse-engineering what AI built. During an incident, that overhead becomes your recovery time. Documentation is not a conservative habit. It is insurance with a known premium.


The Timing Was the Point

If the block had hit during development rather than on the first day of beta, I would have changed DNS on my own device, kept building, and waited for Supabase to resolve it. The client-side code risk would still be in my to-do list. The migration would not have happened. The forced fix only happened because the timing was bad. An active beta with a real team waiting turned a manageable problem into an emergency. The emergency produced a better architecture than I had planned. Without documented code, the same emergency costs a week of recovery, not a day — and produces no architectural improvement, only a patched failure.

The CPU numbers tell a similar story. Cloudflare’s free tier hard limit is 10 milliseconds per request. Before the migration, my average CPU time was 19 milliseconds. After, it is 23 milliseconds. I was already above the limit before I changed anything.

The reason I am not hitting errors is low traffic. Cloudflare enforces the limit softly — occasional spikes do not get terminated. When a worker starts fresh, Cloudflare grants up to 400 milliseconds of CPU leniency for that cold start. With 30 users and inconsistent traffic, most of my requests hit fresh worker instances and pass without penalty.

Once traffic becomes consistent, workers stay warm and cold start leniency disappears. At 23 milliseconds against a 10 millisecond limit, I will need to optimise before that happens — reducing JSON parsing overhead, tightening query handling — or move to the paid plan earlier than planned. This is another metric I had ignored, now in focus because something else broke.

External systems do not check your to-do list before they fail.