AIΒ·NewsTide EditorialΒ·Jul 3, 2026Β·7 min readΒ·πŸ‡ͺπŸ‡Έ ES

Supabase Faces Challenges After 100,000 Active Users: The Connection Pooling, Not Postgres, Is the Issue

When your application on Supabase just surpasses 100,000 simultaneous users, you start encountering inexplicable timeout issues. You've optimized your queries, improved indexes, and cached with Redis. You even invested in the Pro tier hoping that more resources would solve the problem. However, connections continue to fail, and users report sporadic 500 errors. Your monitoring dashboard reveals something curious: Postgres has available CPU, the RAM is fine, and the disks are functioning. The problem is not obvious.

a colorful toy on a table Photo: Shubham Dhage on Unsplash

The real bottleneck in Supabase's scalability is not Postgres or your code, but rather PgBouncer and its management of connection pooling under load. This particularly affects applications with high volumes of ephemeral connections or unexpected traffic spikes. While Firebase was affected by initialization latencies, Supabase gives you the false impression of having scaled when in reality you are saturating an intermediary that, frankly, was never designed to handle so many concurrent connections with complex authentication logic.

The Myth of Transparent Postgres Scalability

Postgres is solid, undoubtedly. Companies like Instagram, Spotify, and Discord use it efficiently to handle millions of users. However, Supabase does not offer you pure Postgres, but a multi-layered architecture that creates friction.

The Supabase stack is as follows: your application β†’ PostgREST (automatic REST API) β†’ PgBouncer (connection pooler) β†’ Postgres. Here's where the first problem arises: PgBouncer operates in "transaction pooling" by default, releasing connections after each transaction. It sounds efficient, but if your application uses prepared statements or session-level variables, PgBouncer is forced to keep connections open longer than expected.

This behavior causes a domino effect in production. A query that would normally take 50ms might be left waiting for an available connection in PgBouncer. Suppose your application handles 500 requests per second with a latency of 100ms: you would need at least 50 concurrent connections. However, Supabase's Pro tier limits connections to Postgres: 60 in the standard, 120 in the Pro. Upon reaching that limit, incoming connections wait in line, which, if filled too quickly, could break your application.

The Real-time and Auth Trap

Supabase promotes real-time as an almost magical feature: real-time subscriptions to changes in your database without additional code. However, each active subscription consumes a persistent connection. With a collaborative dashboard and 1,000 users in real-time, you've already used 1,000 connections. Add to this JWT authentication that validates each request with additional queries to auth.users, and your 120 available connections disappear in the blink of an eye.

The problem lies in that Supabase does not offer detailed metrics of connection usage by features. You see total connections, but not how many occupy real-time subscriptions, API queries, or authentication tasks. When trying to solve a timeout, you wonder: where is the real bottleneck?

The Architecture Supabase Doesn't Document

a purple background with a black and blue circle surrounded by blue and green cubes Photo: Deng Xiang on Unsplash

In 2024, a backend team in a European fintech migrated to a managed Postgres instance on AWS RDS. Not because Postgres couldn't scale, but because Supabase added abstraction layers impossible to optimize under load.

Their problem: real-time notifications where each user had 5 to 20 active subscriptions. With 10,000 connected users, that equates to 200,000 connections. Supabase manages this with a separate Realtime server using Phoenix Channels, but each channel validates permissions by querying Postgres. The result: "real-time" notifications with latencies of up to 3 seconds.

The solution was complex: they implemented a multiplexing system with Elixir, maintaining a persistent connection to Postgres and serving changes to thousands of users via WebSockets. Thus, they internally rebuilt what Supabase promised.

The Issue with Row Level Security at Scale

RLS (Row Level Security) is key to data-level security in Supabase, defining SQL policies that filter results according to the authenticated user. Although elegant, it has a hidden cost: every RLS query runs additional subqueries to evaluate permissions.

A simple query like:

SELECT * FROM posts WHERE user_id = current_user_id();

With RLS enabled, internally it's:

SELECT * FROM posts 
WHERE user_id = current_user_id() 
AND (
  SELECT has_permission('read', posts.id, auth.uid()) 
  FROM auth.users 
  WHERE id = auth.uid()
);

With 500 requests per second, thousands of subqueries emerge to validate permissions. PgBouncer cannot optimize this, as each transaction is independent. The irony is that RLS is crucial for security in Supabase, but also what prevents significant scaling. Thus, teams end up moving the permission logic to their backend, nullifying the value of Supabase.

The Unspoken 200,000 MAU Barrier

I spoke with three founders of SaaS products on Supabase in 2025, and all encountered the same limit: around 200,000 monthly active users. It's not a documented limit, but it arises from the combination of connection pooling, RLS overhead, and infrastructure costs.

One of them, the founder of a collaborative platform, described it in figures: with 180,000 MAU, their bill on Supabase was $850/month (Pro tier). Upon reaching 220,000 MAU, timeouts arose during usage peaks. Supabase recommended migrating to the Enterprise tier with dedicated connections. The cost? $2,500/month base + overages.

The cost-benefit ratio failed. They migrated to Railway with Postgres and Hasura for GraphQL. Monthly cost: $450, with better latency and control over pooling. The migration took four weeks, but it allowed them to scale to 500,000 users without structural changes.

The Hidden Overhead of PostgREST

PostgREST is brilliant at automatically generating a REST API from your Postgres schema. However, every abstraction has its cost. PostgREST processes complex URLs and translates them into dynamic SQL, adding latency: between 10-30ms per request.

With low volume, it's imperceptible. But with 100,000 daily requests, it generates nearly an hour of accumulated CPU time just in query translation. Furthermore, sitting between your application and PgBouncer, it consumes connections while parsing and validating requests.

Teams needing latencies under 50ms end up creating custom endpoints that interact directly with Postgres, bypassing PostgREST. But then, what remains of Supabase's value? You pay for features you don't use because the architecture doesn't support your scale.

Alternatives When You Hit the Limit

The question isn't if Supabase scales, but what to do when you hit that limit without spending $3,000/month on infrastructure.

First option: Hasura + managed Postgres. Hasura offers native GraphQL with comparable RLS, detailed connection metrics, and configurable pooling. You can use Hasura Cloud or host it on Railway/Fly.io. Cost for 200K MAU: $400-600/month versus $2,500+ on Supabase Enterprise.

Second option: Migrate real-time out of Postgres. Use Supabase for transactional data and shift real-time to Ably or Pusher, freeing up thousands of connections. A fintech client reduced their connection usage by 70%, maintaining functionality.

Third option: Implement your own connection pooling with PgCat. PgCat handles millions of concurrent connections. You can place PgCat between your application and Supabase, controlling pooling strategies without migrating your database. It requires additional infrastructure but gives you time to plan an organized migration.

The True Cost of Scaling in Supabase

Discussions about Supabase often focus on costs, but the real expense isn't in the monthly bill. It's in engineering hours debugging inexplicable timeouts, navigating undocumented limitations, and finally migrating when you could have chosen a more transparent architecture from the start.

Supabase is ideal for MVPs, medium projects, and applications that don't need to support hundreds of thousands of concurrent users. But if your startup grows rapidly, you need to know exactly where the limit is before building critical features on an architecture you won't be able to control.

The Decision No One Wants to Make

The harsh reality is that Supabase works wonderfully until it doesn't. And when it fails, the problems are structural, not configurable. You can't tweak PgBouncer beyond basic parameters. Replacing PostgREST would break the entire stack. Gradually migrating real-time to another solution involves rewriting code.

Successful founders I know chose one of two paths: they planned from the start a hybrid architecture where Supabase is just one component, or they accepted that Supabase is a temporary phase before migrating to infrastructure they control.

What nobody tells you is that the abstraction that makes Supabase initially attractive is the same that limits it in the long run. It's not a flaw, it's a design choice. Does this decision align with your growth roadmap?

Has your startup already hit this limit, or do you still believe more RAM will solve the problem?

Editorial note: This article was generated with AI assistance and reviewed by the NewsTide editorial team to ensure accuracy and relevance. Read our editorial policy.

More on AI

→Mistral 7B in Edtech: Is It Really Advisable to Hand Over Pedagogical Control to a Small Model?→The Hidden Costs of Fine-Tuning on Hugging Face: Why 73% of Models Never Reach Production→Tally Turns Conversational AI into Business Advantage: How They Use ChatGPT to Boost Survey Engagement by 50%→The Unfulfilled Promise of Vercel + Supabase: When Real-Time Takes a Technical Toll→Why AI Agents Like Claude 3.5 Fail in E-commerce: They Learned from Amazon, Not Your Store→Greylock is Not Slack: How Persistent Context Architecture Changes the Rules of Distributed Development→The Real Problem with OpenAI APIs That No One Mentions: How It Handles Autoscaling in Production→Perplexity is Not ChatGPT with Search: Why You're Choosing the Wrong API for Your Product
← Back to homeView all AI β†’