Mission impossible deploy nextjs with supabase auth in firebase

Background

I’ve been wanting to build a small website that lets users sign in with Google, so I started looking for a simple backend solution. That’s when I discovered Supabase—its hosted Postgres database, realtime APIs, and built-in Auth system seemed like the perfect fit. Even though I’d dabbled in Next.js before, I’d never really explored its server-side rendering and middleware features, so this project felt like a great way to learn by doing.

Since I’m more of a “learn as I go” developer, I leaned on ChatGPT to help me draft the initial code. To my surprise, the login page came together almost instantly, and integrating Google Authentication was shockingly straightforward. Running everything locally felt like a breeze: sign-in flows worked, Supabase connected to my database without any hiccups, and SSR pages handled cookies seamlessly.

But just as I was basking in that “it-just-works” glow, I deployed to Firebase Hosting—and the nightmare began.

Struggles

Once I flipped the switch and deployed to Firebase Hosting, my Google login still worked—but suddenly I couldn’t fetch any data from Supabase. Here’s what I discovered:

  1. Firebase’s Next.js deployment model When you deploy a Next.js app to Firebase, all your server-side code (SSR pages and API routes) is bundled into a Cloud Function (running on Cloud Run under the hood). Your static frontend lives in Hosting, and any time it needs server logic, it makes an HTTP call to that Cloud Function.
  2. Environment variables were fine My first suspicion was that the Supabase service key wasn’t being picked up in the function. However, my .env variables loaded correctly in production—so that wasn’t it.
  3. Auth context vanished in production I added console.error() statements inside my SSR function and discovered that all authentication info was coming through as null or {}. Locally, the exact same code could read cookies and identify the user perfectly, but in the Cloud Function it saw nothing.
  4. Cookies sent… but never received In Chrome’s Network panel I could clearly see the supabase-auth-token cookie on every request. Yet in my Cloud Function logs, there was no Cookie header at all. Very odd. ChatGPT suggested it might be a cross-site cookie issue (CORS or missing cookie flags), so I dug deeper.
  5. POST works, GET doesn’t Even more confusing: when I changed my API calls to use POST, cookies arrived in the function and authentication worked as expected. But with GET requests, cookies were totally dropped.

Debug

Middleware

Next.js Middleware and Cookie Handling

Next.js Middleware runs on every incoming request—before your API routes or SSR pages—and gives you access to headers, cookies, and the ability to rewrite or redirect requests. I added a console.log in my middleware to inspect req.cookies, expecting to see my Supabase auth token. But in production, it was always an empty object.

After several back-and-forths with ChatGPT and a deep dive into Firebase’s docs, I finally hit on the root cause: Firebase Hosting’s CDN strips nearly all cookies on GET requests to Cloud Functions, leaving only the special __session cookie. That’s why my POST requests (which bypass the CDN cache) carried cookies through just fine, while every GET quietly dropped them. Now that I knew why cookies weren’t making it to my function, I could focus on configuring cookie flags and middleware to solve the problem.

When using Firebase Hosting together with Cloud Functions or Cloud Run, cookies are generally stripped from incoming requests. This is necessary to allow for efficient CDN cache behavior. Only the specially-named __session cookie is permitted to pass through to the execution of your app.

source

Temp Solution

Next, I tried a different approach: on the client I would grab the Supabase auth cookie, stick it into a custom session field, and send that along with every request. In my browser code I could see the cookie correctly packaged, but when the request went out—even in Chrome’s DevTools—I never saw that session field arrive on the server.

What really caught my eye was that the cookie value was unusually large and appeared split into two parts. At first I wondered why the browser would do that, but then I discovered the true culprit: cookie size limits. Both RFC 2109 and RFC 6265 require user agents to support cookies of at least 4096 bytes—and for many browsers this is also the practical maximum size per cookie source. Once your cookie’s payload exceeds ~4096 bytes, the browser will silently truncate or drop it altogether.

In other words, trying to shove all my authentication state into a single cookie was a non-starter—it simply couldn’t survive the browser’s size restriction. At that point it became clear this approach was impossible, so I had to look for another way to persist my session data through Firebase’s CDN/CDN-backed Cloud Functions.

Result

Finally, I decided to try deploying the exact same Next.js + Supabase Auth setup on Vercel—and to my relief, everything just worked. On Vercel, my middleware correctly saw the Supabase cookies, SSR pages authenticated users, and all data fetched from the database without a hitch. It turns out Vercel’s built-in Next.js support handles cookies natively (no CDN stripping or 4KB limits getting in the way), so I didn’t have to jump through hoops with __session or custom session fields. Deploying on Vercel proved to be the simplest path to a seamless Supabase Auth experience!

Deploy the nextjs to Vercel SAVE ME IN THE END!

comments powered by Disqus