releases.shpreview
Supabase/Supabase Changelog

Supabase Changelog

Mon
Wed
Fri
JunJulAugSepOctNovDecJanFebMarAprMayJun
Less
More
Releases20Avg6/moVersionsv0.1
v0.1

Today we're releasing Multigres v0.1 alpha to the open source community, the first public milestone of our mission to bring Vitess-grade horizontal scaling, high availability, and operational simplicity to Postgres. It's early, it's alpha, and we're excited to get it into your hands.

This is an open-source-only release. Multigres for Supabase is coming soon.

What is Multigres?

Multigres is a scalable operating system for Postgres: it holistically manages your Postgres instances and gives you sharding, connection pooling, automatic failover, and backup orchestration.

Postgres at scale is operationally complex: You need to manage read replicas, failovers, connection limits, backups, and more. Multigres handles these chores as a single cohesive system. And when the time comes to scale, Multigres will help you shard your database and scale it horizontally.

The v0.1 alpha introduces advanced connection pooling, automatic failovers, and a Kubernetes operator for deployment.

The Multigres Operator

The Kubernetes Multigres Operator allows you to deploy and manage Multigres clusters on Kubernetes. To get started, you need a Kubernetes cluster along with a location for backups configured. The backups can be a shared file system or a cloud storage bucket like AWS S3. It is also possible to run Multigres on a local Kind cluster.

All the necessary images for running Multigres are publicly available.

High Availability

Multigres treats HA as a consensus problem, and is capable of resolving split-brain scenarios without losing commits that have succeeded. The protocol implemented by Multigres is based on generalized consensus, a model that gives you flexibilities that do not exist in traditional consensus-based systems:

  • Built on top of Postgres replication: The protocol uses unmodified Postgres replication, and yet satisfies all the strict consistency requirements of a consensus-based system.
  • User-defined durability policies: You can define arbitrarily complex durability policies. This flexibility allows you to specify the failures you are willing to tolerate without being constrained by restrictive rules like a majority quorum. For example, if you'd like your data to survive the failure of a single AZ, you can set your durability policy to be cross-zone, but still have standbys deployed in more than three zones.
  • Add or remove replicas without affecting performance: You can safely scale replicas up and down while the cluster is running. Multigres will continue to honor the durability policy you've configured without affecting performance, while also maintaining correctness.

For more information on HA, you may read the following posts:

Connection Pooling

Multigres ships its own connection pooling solution using a two-service architecture. It consists of a multigateway that accepts client connections and routes queries, and a multipooler that manages backend connections. This architecture provides some distinct advantages over a single-process pooler.

  • Traffic routing: The integration with the HA system allows multigateway to transparently route connections to the current primary. During a failover, multigateway can hold requests until a new primary is promoted, thereby minimizing errors. Additionally, you can balance read load across multiple replicas. In the future, multigateway will handle routing of traffic to different shards.
  • Context-aware pooling: Multigres does not require you to choose a pooling mode like transaction, session, etc. This is because it has a built-in parser and understands the effects of each request. This allows it to track connection state and reuse them wherever applicable. If a request requires a stateful connection, like a transaction, the connection gets pinned to that client until the stateful requirement is satisfied.
  • Per-user pools: Multigres maintains a separate connection pool per user with no shared pool and no SET ROLE impersonation. A fair-share algorithm splits a fixed connection budget across users, and pool routing is kept fast.
  • Prepared statement consolidation: Multigres deduplicates prepared statements across gateways. Postgres parses, plans, and caches a given statement once, no matter how many gateways are forwarding it.

For more information on connection pooling, you may read Two jobs, two processes: why Multigres has its own connection pooler.

Backups

Multigres uses pgBackRest for backups. Backups are taken from replicas to avoid overloading the primary.

  • Three backup types: full backups copy the entire data directory at a checkpoint; incremental backups copy only files changed since the previous backup; differential backups copy changes since the last full backup. A typical schedule runs full backups periodically with more frequent incrementals or differentials in between.
  • On-demand and scheduled: the CLI lets you list backups, trigger a manual backup, and initiate a restore. We'll soon add support for scheduled backups through the cluster spec.
  • Bootstrap: During bootstrap, Multigres automatically identifies a primary, performs a backup, and uses it to initialize the other replicas. This workflow brings up a ready-to-run cluster without any manual intervention.

To learn more about how a cluster bootstraps, you may read How a Multigres Cluster Bootstraps.

What alpha means

v0.1 is stable enough to experiment with and give feedback on. It is not yet ready for production workloads. Specific caveats:

  • We have known issues that still need to be addressed.
  • Sharding (the eventual flagship feature) is not in this release. v0.1 is a single-shard cluster with HA and pooling.
  • Future releases are not guaranteed to be backward compatible.
  • The CR API is not yet stable. Fields may change before v1.0.
  • Performance benchmarks are in progress. We'll publish numbers in a follow-up post.

Try Multigres

  1. Deploy your first cluster: a minimal CR that stands up a 3-node HA cluster.
  2. Join the community: file issues and request features at github.com/multigres/multigres. Post your thoughts in github.com/multigres/multigres/discussions to discuss features and get help.

Supabase has raised a $500M Series F at a $10B pre-money valuation. It's led by GIC. All existing investors joined the round, Stripe made a second investment. Georgian and Salesforce Ventures joined as new investors.

The round is for three things:

  • Accelerate development of open source / Postgres tools.
  • To support our growth.
  • Liquidity for the employees.

Open source development#

Today we're releasing Multigres v0.1 alpha. It's open source and self-hostable.

Postgres is hard to run at scale. Multigres is a scalable operating system for Postgres that provides high availability and operational simplicity. In a future release it will provide Vitess-grade horizontal scaling.

The alpha status is to signal that it's ready to try, but not yet production-ready. We'll get there in a few months. If you're running a large Postgres workload you can apply to be a Multigres partner and help shape the direction of Multigres.

Multigres will be available on the platform when it moves out of alpha. Together with our work on OrioleDB (targeting production-readiness this year), we believe that we will have a complete Postgres solution that solves many hairy Postgres problems, including bloat, connection pooling, and Jepsen-level high availability. Sharding is also on the menu - we'll share more details later.

Supabase growth#

In the past year, database launches on Supabase have grown 600%. More than 60% of new databases are launched by some sort of AI tool.

Nearly 10 million developers build on Supabase today, more than doubling since our last fundraising announcement eight months ago. Growth is accelerating since January as Claude Code and Codex expand the number of people who can build.

A lot of our growth is also thanks to our partners, platforms that build on top of Supabase. Supabase for Platforms has been the fastest growing product over the last year.

Managing infrastructure at our scale brings a unique set of challenges. We're using this funding to invest in the not-so-visible platform features: performance, reliability, and support teams to help our customers. Postgres can be hard to manage, even for experienced DBAs, and we're investing in tooling that helps builders run their databases autonomously.

Employee secondaries#

Supabase has employees in over 50 countries now. We are always looking for the "best person for the job", no matter where they live. We don't do geo-adjusted salaries - people get paid for the result of their work, not the city they live in.

We approach stock options with a similar mindset. Employees have 10 years to exercise, even if they decide to leave. In every round, we offer our employees to sell up to 25% of their vested stock. This provides liquidity long before we reach the public market.

Check out our careers page if you'd like to join our global remote and async team.

To the community#

I work at Supabase because we're open source. Building for a community of builders is the thing I care most about. One of Supabase's principles is to support existing tools, working collaboratively with the open source community.

Thank you to everyone who has helped along the way, especially those who have contributed directly or indirectly to the tools that make up the Supabase ecosystem.

There has been a growing trend of supply chain attacks on Node Package Manager (NPM). In addition, we have seen other creative attacks, including a typosquat package named supabase-javascript that appeared on npm, copying our name to phish developers. We reported it. npm took it down a few hours later, long enough that the package picked up real downloads.

If you build on Supabase, this matters to you. Edge Functions pull from npm. The Supabase CLI is on npm. supabase-js, @supabase/ssr, and @supabase/server are all on npm. Any of these is a credential leak waiting for the wrong update to land.

This post lays out what we are doing about it and what you should do today.

What we are doing about it at Supabase#

We kicked off a coordinated response across the company. The work in flight:

  • Publishing a canonical security guide in our docs. A single, agent-readable page that tells you exactly what to do.
  • Hardening our own GitHub Actions. Our security team finished a pass on pull_request_target usage across the Supabase org months ago and is close to enforcing pinned action SHAs across every repo.
  • Adding security notes to secret-handling APIs. TSDoc and JSDoc on functions like createClient so editor hovers warn when you are working with sensitive credentials.
  • Comms across every channel. Our goal is to educate as many people as we can, whether or not they are Supabase customers.

How npm supply chain attacks actually happen#

Supply chain attacks share a shape. The attacker does not break into your computer. They get you to invite their code in, and they do that by getting their code into a package you already trust. The recipes vary, but the three most common patterns are these:

  • Maintainer compromise. An attacker steals an npm publish token or phishes a maintainer, then publishes a new version of a popular package with malicious code added. The next time you run npm install against that range, you are running their code.
  • Typosquatting. An attacker registers a package name a few letters away from a real one, like supabase-javascript instead of @supabase/supabase-js. They wait for a developer or, increasingly, an AI coding agent to mistype the name. AI agents hallucinate package names regularly, and that is now a primary attack vector against teams that vibe-code their dependencies.
  • Build pipeline compromise. This is what hit TanStack. An attacker found a vulnerable GitHub Actions workflow, poisoned the build cache from a fork PR, and waited for the next legitimate release run to pick up the poisoned cache and publish their code under the real maintainer's identity. No stolen tokens. No compromised laptops. The attacker rode the official release train.

Once the malicious code lands on disk in your node_modules, npm's lifecycle scripts run it. By the time npm install returns, the attacker has already read your environment variables, your AWS instance metadata, your kubeconfig, your .npmrc token, your .git-credentials, and your SSH private keys. The TanStack payload exfiltrated through the Session messenger network, which is end-to-end encrypted and has no fixed command-and-control address. You cannot block it at the firewall.

The TanStack postmortem describes the full chain and is worth reading if you maintain a public open source project. The short version: every link in the chain (a pull_request_target workflow, an unsecured Actions cache, a long-lived OIDC publish token) was a known issue with public mitigations. The attack worked because nobody had connected the dots in advance.

Other things you should do today#

Most of what follows takes minutes. The goal is layered defense: no single mitigation stops every attack, but together they raise the cost enough that attackers go bother someone else.

Upgrade to pnpm 11 (or the npm v11 equivalent)#

pnpm 11 sets minimumReleaseAge to 24 hours by default, blocks exotic subdependencies by default, and ships a new Allow Builds model that controls which dependencies are permitted to run install scripts. If your AI coding agent picked pnpm 10.x for you, fix that. Tell it to use pnpm 11.

Then set minimumReleaseAge higher than the default. Three to seven days is a reasonable starting point for most projects. Most malicious npm packages are caught and pulled within twenty-four to forty-eight hours, so a three-day window catches the long tail of detections without throttling legitimate updates too much. Configure it in your project's pnpm-workspace.yaml or .npmrc:

minimumReleaseAge: 4320 # minutes, equals 3 days
Pin versions, especially for security-sensitive dependencies#

The ^ and ~ ranges in your package.json are a polite way of telling npm "trust me, take the next minor or patch version." Supply chain attacks exploit exactly that trust. Pin exact versions for anything that touches authentication, secrets, networking, or user data. Use ^ only where you actively want updates and have a process to vet them.

Commit your lockfile and review changes to it#

A lockfile records exactly which version of which package, with which hash, you installed. If an attacker republishes a tarball under the same version number, the hash mismatch fails the install. Commit pnpm-lock.yaml, package-lock.json, or yarn.lock to your repo. Treat lockfile diffs as code review surface, not noise. A pull request that bumps fifty transitive dependencies for no obvious reason deserves a careful read before it merges.

Disable npm install scripts where you can#

Most supply chain payloads run through preinstall, install, or postinstall lifecycle scripts. If your project does not need them, turn them off globally:

npm config set ignore-scripts true

Or scope it to the project via .npmrc:

ignore-scripts=true

The trade-off is that some packages with native code (bcrypt, sharp, and similar) will not build without scripts. Use pnpm's Allow Builds model to allowlist the specific packages you actually need rather than allowing every package on the registry to run code at install time.

Verify package names every single time you install#

Typosquats target the moment of carelessness. Before you pnpm add anything, especially anything an AI agent suggested, check that:

  • The scope is correct. Official Supabase packages live under @supabase/. A package named supabase-javascript or supabase-server without the scope is not ours and never has been.
  • The maintainer is the expected one. The npm page lists current maintainers; a brand-new maintainer on a long-established package is a signal worth a closer look.
  • The download counts and the linked GitHub repo match what you expect for a real, established package.
Pin your GitHub Actions to commit SHAs, not tags#

If you maintain a public repo, this is the single biggest change you can make. A tag like @v5 is a moving target. The maintainer of that action (or an attacker who compromised that maintainer) can republish the tag with new code, and your workflow will pick it up on the next run. Pin to the full commit SHA instead:

- uses: actions/checkout@1f9a0c22da41e6ebfa534300ef656b67ce0c5b94 # v6.0.2

Renovate and Dependabot both understand this syntax and will update the comment when a new release is published, so you still get visibility without giving up safety.

Avoid pull_request_target with code checkout#

If your workflow uses pull_request_target and then checks out code from the PR, you are running attacker-controlled code in a context that has access to your repo's secrets and cache. This is the exact pattern that compromised TanStack. Use pull_request for anything that touches PR code. Reserve pull_request_target for trusted, no-checkout operations like labeling or commenting on the PR.

Rotate credentials if you think you were exposed#

If you ran npm install on a day when a package you depend on turned out to be compromised, treat the install host as potentially compromised too. Rotate everything reachable from that machine: AWS, GCP, Kubernetes, Vault, GitHub, npm, SSH, and any Supabase service-role keys. Audit your service-role key usage in the Supabase dashboard for access patterns you do not recognize. It is an annoying afternoon. It is not as annoying as a customer breach.

Consider a scanner as a second line of defense#

Tools like Socket.dev, npq, and Snyk monitor the npm registry and flag suspicious package behavior in real time. None of them are a silver bullet, and none of them substitute for the practices above. They are a useful second line of defense for teams that already have the basics in place.

Closing thought#

This kind of attack will keep happening. The cost of pulling one off keeps dropping; the payoff (credentials to dozens of production systems in a single shot) keeps rising. The good news is that the defenses are well understood, cheap to implement, and effective when stacked. Pin your versions. Wait for the dust to settle on new releases. Lock your CI down. Verify what you install. Tell your AI agents to do the same.

If you have suggestions, requests, or your own war stories about how you handle this on your team, find me on Discord or on Twitter.

Prompt for your coding agent#

Paste this into Claude Code, Codex, Cursor, or whatever agent you use. Read every change before you accept it. Do not skim.

Audit this repo for npm supply-chain hygiene. Apply the changes below and report what you did. Do not push, open PRs, install new dependencies, or rotate credentials without explicit approval.

Package manager:

- Upgrade to pnpm 11+ (or the latest yarn / npm / bun) if older.
- Set a 7-day quarantine on new versions for the package manager in use:
 - pnpm: `minimumReleaseAge: 10080` in `pnpm-workspace.yaml`.
 - npm: `min-release-age=7` in `.npmrc`.
 - yarn (berry): `npmMinimalAgeGate: '7d'` in `.yarnrc.yml`.
 - bun: `minimumReleaseAge = 604800` under `[install]` in `bunfig.toml`.
- Block lifecycle scripts by default. pnpm: declare an explicit `allowBuilds` list in `pnpm-workspace.yaml`. npm/bun: set `ignore-scripts=true`. yarn defaults to `enableScripts: false` — confirm it is not overridden.
- Block non-registry transitive refs. pnpm: `blockExoticSubdeps: true`. npm: set `allow-git=root`, `allow-remote=root`, `allow-file=root`, `allow-directory=root` in `.npmrc`. yarn: use `approvedGitRepositories` as an explicit allowlist.
- Pin the package manager itself: set `packageManager` in `package.json` to an exact version plus sha512 hash (e.g. `pnpm@10.4.1+sha512.<hash>`).

Lockfile and dependencies:

- Confirm `pnpm-lock.yaml`, `package-lock.json`, or `yarn.lock` is committed (not gitignored). CI installs must use `--frozen-lockfile` (pnpm/yarn) or `npm ci`. Flag any job that runs a non-frozen install.
- For dependencies handling auth, secrets, networking, crypto, or user data, replace `^`/`~` ranges with exact versions. List what you changed.
- Verify every Supabase import uses the exact `@supabase/` scope. Flag unscoped lookalikes (`supabase-js`, `supabase-javascript`, etc.) as possible typosquats.

GitHub Actions (if present):

- Repin every third-party `uses:` reference to a 40-character commit SHA, with the original tag as a trailing comment.
- Flag every workflow using `pull_request_target` that checks out PR code or runs PR-controlled build steps. Propose a `pull_request` rewrite. Do not silently change trigger types.
- Add a non-blocking `npm audit signatures` step to install workflows.

Flag for human (do not auto-enable):

- Dependabot alerts and secret scanning, if disabled.

Report:

- One line per file changed, with the reason.
- A separate list of items flagged for human review rather than automatically changed.

Supabase is now an official app in ChatGPT. Connect your Supabase projects and manage your entire database infrastructure by telling ChatGPT what you need.

With the Supabase ChatGPT app, you can execute SQL queries, modify schemas, deploy edge functions, manage branches, and troubleshoot your projects without leaving your conversation with ChatGPT.

Ask ChatGPT to check security advisors on your project and fix any issues. Request a schema change and ChatGPT executes it. Deploy an edge function with a single prompt.

What you can do#

The Supabase ChatGPT app includes 29 tools:

  • Database management: Execute SQL queries on Postgres databases, design and modify table schemas, list tables and extensions, get security recommendations.
  • Project operations: List and create projects, get cost estimates, pause and restore projects, access real-time logs.
  • Branching and migrations: Create development branches, merge changes, rebase and reset branches, list and apply migrations.
  • Edge functions: List, deploy, and manage serverless functions.
  • Documentation: Search Supabase docs directly from ChatGPT.

You can also pair the app with ChatGPT Projects to scope a conversation to a specific Supabase project. Set your project reference in the project instructions once, and every chat in that project connects to the right database automatically.

Getting started#

In ChatGPT, open the app directory and search for Supabase, or go directly to the app listing. Authorize ChatGPT to access your Supabase organization.

The app works on all Supabase plans and paid ChatGPT plans (Plus, Pro, Team, Enterprise).

If you don't have a Supabase account yet, start your project for free at supabase.com. Then connect it to ChatGPT and manage your projects by describing what you need.

Read the documentation at supabase.com/docs/guides/getting-started/mcp.

Today we're releasing @supabase/server in public beta.

This is a new package that handles auth verification, client setup, request context, and common server-side boilerplate for you. It works across Edge Functions, Vercel Functions, Cloudflare Workers, Hono and Bun.

We anonymously analyzed 25,000 deployed Edge Functions and saw the same pattern everywhere: developers were rebuilding the same setup code over and over just to get to their actual business logic.

Most functions needed to:

  • Create a Supabase client with SUPABASE_ANON_KEY
  • Create another admin client with SUPABASE_SERVICE_ROLE_KEY that can bypass Row Level Security
  • Verify the JWT
  • Parse claims
  • Handle CORS
  • Wire up auth context
  • Copy/paste the same _shared/*.ts files between functions

With @supabase/server you just declare who can call your endpoint and get a fully initialized context back:

  • User-scoped Supabase client
  • Admin client with service role access
  • Verified user identity
  • JWT claims
  • Built-in request/auth helpers
import { withSupabase } from 'npm:@supabase/server'

// Typical Deno.serve usage
Deno.serve(
  withSupabase({ auth: 'user' }, async (req, ctx) => {
    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  })
)

// New fetch style handler usage
export default {
  fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  }),
}

Note that export default { fetch } is equivalent to Deno.serve(...). Both define a request handler. We use export default throughout this post because it works across Edge Functions, Workers, and Bun. If you prefer Deno.serve, you can keep using it — it's still supported on Edge Functions.

How it works#

At the core of @supabase/server is the SupabaseContext: a request context that includes everything most Edge Functions need, already configured for you.

That includes:

  • A user-scoped Supabase client
  • An admin client with service role access
  • Verified user identity
  • JWT claims
  • Auth metadata

@supabase/server gives you multiple ways to get a SupabaseContext. The most common is withSupabase, a wrapper that handles auth, client creation, and CORS before your handler runs:

import { withSupabase } from 'npm:@supabase/server'

export default {
  fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  }),
}

If you need more control over error handling and responses, you can also call createSupabaseContext directly:

import { createSupabaseContext } from 'npm:@supabase/server'

export default {
  fetch: async (req) => {
    const { data: ctx, error } = await createSupabaseContext(req, { auth: 'user' })
    if (error) return Response.json({ error: error.message }, { status: error.status })

    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  },
}

Both approaches give you the same SupabaseContext. No shared utility files. No environment variable management. No manual JWT verification.

What's in the context#

Every withSupabase handler receives a ctx object with two pre-configured clients:

ctx.supabase — a user-scoped client that automatically respects RLS policies ctx.supabaseAdmin — an admin client using the service role for privileged operations

No manual client setup, JWT verification, or environment variable wiring required.

The full context looks like this:

interface SupabaseContext {
  supabase: SupabaseClient
  supabaseAdmin: SupabaseClient
  userClaims: UserIdentity | null
  jwtClaims: JWTClaims | null
  authMode: AuthMode
}

Declarative access control#

With @supabase/server, authentication happens before your handler runs.

You declare who is allowed to call the endpoint, and the package handles verification automatically.

For example, this endpoint allows unauthenticated requests:

export default {
  fetch: withSupabase({ auth: 'none' }, async (_req, _ctx) => {
    return Response.json({ status: 'ok' })
  }),
}

This endpoint requires a valid user JWT:

export default {
  fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  }),
}

If the request does not include a valid user token, the request is rejected before your handler executes.

Here's all of the auth modes included in the package:

// authenticated users only (default)
withSupabase({ auth: 'user' }, handler)

// no auth required, good for webhooks and health checks
withSupabase({ auth: 'none' }, handler)

// server-to-server with secret key
withSupabase({ auth: 'secret' }, handler)

// with publishable key
withSupabase({ auth: 'publishable' }, handler)

// accept either a user JWT or a secret key
withSupabase({ auth: ['user', 'secret'] }, handler)

Your function's security model is visible in one line.

Adopting new auth keys without the boilerplate#

Last year we improved project security with asymmetric JWT Signing Keys and new API keys. Better security for every project, but migrating existing functions was hard.

You had to install jose, configure a JWKS endpoint, build your own auth middleware, expose new secrets, and update every function individually.

We fixed it. @supabase/server handles new key validation and JWT verification internally. You adopt the package and the new security model comes with it. No jose. No JWKS configuration. No manual secret setup.

export default {
  // auth: 'user' will handle incoming user JWT validation for you
  fetch: withSupabase({ auth: 'user' }, async (req, { supabase }) => {
    const { data } = await supabase.from('subscriptions').select('*')
    return Response.json(data)
  }),
}

Now you get support for the new auth keys without manual JWT verification. Delete your shared utility files and focus on business logic.

Same code, every runtime#

withSupabase returns a standard (Request) => Promise<Response> handler. It works with any runtime that supports the Web API pattern.

Edge Functions, Vercel Functions, and Cloudflare Workers:

import { withSupabase } from '@supabase/server'

export default {
  fetch: withSupabase({ auth: 'user' }, handler),
}

On Edge Functions, declare the dependency in deno.json to import @supabase/server from npm:@supabase/server.

Hono (with the included adapter):

import { withSupabase } from '@supabase/server/adapters/hono'
import { Hono } from 'hono'

const app = new Hono()

app.get('/todos', withSupabase({ auth: 'user' }), async (c) => {
  const { supabase } = c.var.supabaseContext
  const { data } = await supabase.from('todos').select()
  return c.json(data)
})

export default { fetch: app.fetch }

Composable primitives#

Most developers don't need anything beyond withSupabase or createSupabaseContext. But you can use the underlying primitives directly.

import {
  createAdminClient,
  createContextClient,
  resolveEnv,
  verifyAuth,
} from '@supabase/server/core'

These are useful when you need more control: multiple routes with different auth, custom response headers, or domain-specific wrappers like MCP servers.

Here's an Edge Function with per-route auth:

import { createContextClient, verifyAuth } from '@supabase/server/core'

export default {
  fetch: async (req) => {
    const url = new URL(req.url)

    if (url.pathname === '/health') {
      return Response.json({ status: 'ok' })
    }

    if (url.pathname === '/todos') {
      const { data: auth, error } = await verifyAuth(req, { auth: 'user' })
      if (error) return Response.json({ error: error.message }, { status: error.status })

      const supabase = createContextClient(auth.token)
      const { data } = await supabase.from('todos').select()
      return Response.json(data)
    }

    return new Response('Not found', { status: 404 })
  },
}

These are the same primitives that power withSupabase. Teams building MCP servers, custom middleware, or framework adapters can compose them into their own patterns.

One pattern for humans and AI agents#

We designed @supabase/server with agentic development in mind. Every function follows the same structure: declare access, receive context, write logic.

During internal testing, Claude Code migrated an entire project's Edge Functions to @supabase/server in a single prompt. That included adopting new API keys, removing shared utility files, and switching every function to withSupabase. All functions worked on the first run.

When every function looks the same, agents produce correct code from a single example.

FAQ#

Does this replace @supabase/ssr?

No. @supabase/ssr handles cookie-based session management for frameworks like Next.js and SvelteKit. @supabase/server handles stateless, header-based auth for Edge Functions, Workers, and other backend runtimes. The two packages coexist and are not replacements for each other. Deeper integration with @supabase/ssr is on the roadmap.

If you would like to adopt the DX that this package provides, check our SSR frameworks documentation for implementation references.

Which runtimes does this support?

Any runtime or platform that supports the standard Request/Response Web API. withSupabase returns a standard (Request) => Promise<Response> handler, so it works on Supabase Edge Functions, Vercel Functions, Cloudflare Workers, Bun, Deno and more.

Is Hono the only supported framework?

No. Hono was the first framework adapter we shipped, and we have already merged a community PR for the H3 adapter. We expect to accept more community-contributed adapters.

See more in our adapters documentation.

Where is the documentation?

The package ships with full documentation in the GitHub repo. We're also working on adding guides to the Supabase docs.

What about environment variables?

On the Supabase platform and Local Development (CLI), your Edge Functions will receive the required environment variables to work out of the box (SUPABASE_PUBLISHABLE_KEYS, SUPABASE_SECRET_KEYS, SUPABASE_JWKS).

In local development or self-hosted environments, use the same plural form: SUPABASE_PUBLISHABLE_KEYS instead of SUPABASE_ANON_KEY, SUPABASE_SECRET_KEYS instead of SUPABASE_SERVICE_ROLE_KEY.

Check out the environment variables documentation for more details.

How can I leave feedback?

Open an issue on the GitHub repo or join the conversation in Discord.

Get started#

Install the package and the AI skill:

npm install @supabase/server@latest
npx skills add supabase/server

The skill gives Claude Code, Codex, Cursor and any agentic coding tool full context about the API surface, patterns, and migration paths. From there, you can prompt your way through most tasks.

Analyze all Edge Functions, and plan a full migration to use
the new API keys with @supabase/server

Scaffold a new REST API with Hono:

Create a Hono API with @supabase/server that has CRUD
endpoints for a todos table, using per-route auth

Add a protected Edge Function with admin operations:

Create an Edge Function that accepts user or secret key auth,
reads from a user's profile with RLS, and writes audit logs
with the admin client

Or write it by hand:

import { withSupabase } from 'npm:@supabase/server'

export default {
  fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  }),
}

@supabase/server is in public beta. We're looking for feedback on the API surface, the adapter patterns, and edge cases we haven't hit yet.

Check out the GitHub repo and the docs and let us know what you build.

Both Supabase Realtime and Supabase ETL read changes from your Postgres database. They both use logical replication under the hood. They even look similar when you squint. But they solve very different problems, and choosing the wrong one will frustrate you.

This post explains what each product does, how they differ, and when you should pick one over the other.

Two tools, two jobs#

Here is the simplest way to think about it:

  • Realtime sends database changes to your users' browsers and apps, right now, as they happen. It is built for live experiences.
  • ETL sends database changes in near real-time to analytical destinations like BigQuery and Analytics Buckets. It is built for reliable data movement.

Realtime answers the question: "How do I show my users what just happened?"

ETL answers the question: "How do I get my production data into my analytics warehouse?"

If you mix these up, you will run into problems. We see it happen regularly, and the rest of this post will help you avoid that.

What Realtime does#

Supabase Realtime is three features in one product:

  1. Broadcast. Send messages between connected clients in real time. No database required. Think cursor positions, typing indicators, or game state.
  2. Presence. Track who is online and what they are doing. Also no database required. Think "3 users are editing this document" or "Jane is typing..."
  3. Postgres Changes. Listen to INSERT, UPDATE, and DELETE events on your database tables and deliver them to subscribed clients over WebSocket.

Two of these three features, Broadcast and Presence, can work without any database interaction. Client-to-client Broadcast sends messages purely over WebSocket with nothing stored. However, Broadcast from Database lets you trigger broadcasts from database changes using triggers, giving you control over which events reach which channels. This matters because Realtime is not just a database change listener. It is a real-time communication layer for your application.

How Postgres Changes works#

When a client subscribes to a table, Realtime uses a PostgreSQL replication slot to read changes from the Write-Ahead Log (WAL). For each change, it checks Row Level Security (RLS) policies against every subscribed user. If a user is authorized to see the change, Realtime sends it over their WebSocket connection.

This is designed for live UI updates. A user inserts a message into a chat table. Other users see it appear instantly. A row updates in a dashboard table. The chart refreshes automatically.

What Realtime does not guarantee#

Realtime's Postgres Changes feature does not guarantee delivery. If a client disconnects for 30 seconds and reconnects, the changes that happened during those 30 seconds are gone. Realtime does not queue them and does not track how far each client has read.

Broadcast Replay offers limited catch-up for Broadcast from Database messages: clients can request up to 25 messages from the last 3 days using a since timestamp. But this only works on private channels, only for database-sourced broadcasts, and is currently in public alpha. It is not a general-purpose replay mechanism for all Realtime events.

Postgres Changes uses temporary replication slots. When no clients are subscribed, it stops replicating data entirely. When clients subscribe again, a new slot is created.

The Realtime team built it this way on purpose. Guaranteed delivery requires persistent state tracking, message queuing, and acknowledgment protocols. Those things add latency and complexity that would make Realtime worse at its actual job: delivering live updates as fast as possible.

If you need every change to arrive at its destination, no matter what, Realtime is not the right tool.

What ETL does#

Supabase ETL is a change-data-capture (CDC) pipeline. It reads every INSERT, UPDATE, DELETE, and TRUNCATE from your Postgres tables and writes them to a destination. Right now, the supported destinations are Analytics Buckets (built on Apache Iceberg) and BigQuery.

ETL replicates your data 1-to-1 in near real-time. If your destination disconnects or has problems, ETL does not skip over data.

How ETL works#

When you create an ETL pipeline, it connects to your database through a permanent replication slot. First, it performs a full copy of your existing data. Then it switches to streaming mode and captures every change as it happens, with latency measured in milliseconds to seconds (based on configuration parameters, data size, and destination type).

It's important to note that Supabase ETL doesn't respect Row-Level Security. Supabase ETL reads every piece of data. If you need to filter data, you should use publication filters.

Changes are batched and written to your destination. If the pipeline crashes, it restarts from the last acknowledged position. No data changes are lost. Note that schema changes (adding or removing columns) do not propagate automatically and require manual handling.

What ETL guarantees#

ETL provides at-least-once delivery. Every change that happens in your database will reach the destination at least once. In rare cases (like a crash during a long-running transaction), a change might be delivered more than once. Exactly-once processing is handled by the destination. Some destinations like BigQuery deduplicate automatically, while others may not.

ETL uses permanent replication slots. This means Postgres holds onto WAL data until ETL confirms it has been processed. If you stop the pipeline for maintenance and restart it later, it picks up exactly where it left off. Be aware that while the pipeline is paused, Postgres continues to retain WAL data. Extended pauses can lead to significant disk growth, and depending on your Postgres configuration, the pipeline may fail if the WAL retention limit is exceeded.

This is the opposite of Realtime's approach. ETL trades speed for reliability. It may not deliver changes to your warehouse in the same millisecond they happen, but it will deliver every single one.

The key differences#

Delivery guarantees#
RealtimeETL
GuaranteeBest effortAt-least-once
Missed changesLost foreverReplayed on reconnect
Replication slotTemporaryPermanent
Resume after disconnectNoYes

This is the most important difference. If you need every change to arrive, use ETL. If you need changes to arrive fast and can tolerate occasional gaps, use Realtime.

Where data goes#

Realtime sends data to client applications over WebSocket connections. Your users' browsers and mobile apps are the destination.

ETL sends data to analytical systems. BigQuery, Analytics Buckets, and eventually other data warehouses are the destination.

These are fundamentally different targets with fundamentally different needs. Client apps need low latency. Analytical systems need completeness.

Database dependency#

Realtime's Broadcast and Presence features can work without touching the database. You can build an entire collaborative experience (cursors, presence indicators, ephemeral messaging) without writing a single database query. However, Postgres Changes and Broadcast from Database both require database interaction.

ETL is entirely database-driven. Every byte of data it moves comes from your Postgres tables.

Scale characteristics#

Realtime's Broadcast and Presence features are built for high throughput and low latency. They do not run per-subscriber database queries and scale well across many concurrent connections.

Postgres Changes works differently. It processes changes sequentially to maintain ordering. For each change, it runs an RLS authorization check against every subscribed client. With 100 subscribers watching a table, one INSERT generates 100 authorization queries. This is a deliberate design choice that prioritizes correctness and low latency for typical workloads over raw throughput.

ETL processes changes in configurable batches with tunable parallelism. It does not need to authorize individual users because it is moving data to a system, not to end users.

When to use Realtime#

Use Realtime when you need to push live updates to your users:

  • Chat applications. Messages appear instantly for all participants.
  • Collaborative editing. See other users' cursors and changes in real time.
  • Live dashboards. Charts and metrics update without page refresh.
  • Notifications. Alert users when something relevant happens.
  • Multiplayer features. Synchronize game state or shared experiences.
  • Presence tracking. Show who is online, who is typing, who is viewing a document.

The common thread: a human is watching and needs to see changes as they happen.

When to use ETL#

Use ETL when you need reliable data movement to analytical systems:

  • Analytics and reporting. Move production data to BigQuery or Iceberg for querying without impacting your production database.
  • Audit trails. Analytics Buckets stores an append-only changelog of every INSERT, UPDATE, and DELETE. Nothing is lost.
  • Data warehousing. Replicate your operational data to a columnar format optimized for analytical queries.
  • Compliance. Maintain a complete, verifiable history of all data changes.
  • ML pipelines. Feed fresh data to training or feature stores without querying production.
  • Workload isolation. Run heavy analytical queries against your warehouse instead of your production database.

The common thread: a system needs a complete, reliable copy of your data.

The mistake we see most often#

Some developers discover Realtime's Postgres Changes feature and think: "I can use this to replicate data from one system to another." They write 20 lines of code with supabase-js, subscribe to table changes, and pipe them into another system.

It works great in development. It even works fine in production for a while. Then a WebSocket connection drops for a few seconds and data goes missing. Or the subscribing process restarts and misses a batch of changes. Or load spikes and the sequential RLS authorization checks cannot keep up.

The problem is not that Realtime is broken. The problem is that Realtime was not designed for this job.

If you are piping database changes into another system and you need every change to arrive, use ETL. That is exactly what it was built for.

Can I use both?#

Yes. In fact, many applications should.

Consider an e-commerce platform. You might use Realtime to push order status updates to customers in real time ("Your order has shipped!"). At the same time, you use ETL to replicate all order data to BigQuery for daily sales reports and trend analysis.

Same database. Same tables. Different tools for different jobs.

Realtime handles the live experience. ETL handles the analytical pipeline. Each does what it was designed to do.

Quick reference#

RealtimeETL
PurposeLive updates to client appsReliable data movement to analytics
DeliveryBest effortAt-least-once
DestinationsBrowsers, mobile apps (WebSocket)BigQuery, Analytics Buckets
Replication slotTemporaryPermanent
Resume on reconnectNoYes
Database requiredOnly for Postgres Changes and Broadcast from DatabaseYes, always
ProcessingSequential per-change with per-subscriber authorizationBatched with configurable parallelism
LatencyTypically under 100msSeconds (batched)
Best forHuman users watching live dataSystems consuming complete data
Built withElixir (Phoenix)Rust
Open sourcegithub.com/supabase/realtimegithub.com/supabase/etl

Getting started#

Supabase Realtime is available on all Supabase projects. Check out the Realtime documentation to get started.

Supabase ETL is currently in private alpha. You can request access through the Supabase Dashboard or contact your account manager. Read the ETL blog post for more details on how it works.

Branching without Git is now the default for all Supabase projects.

Supabase has supported database branching through a git-based workflow since Launch Week X. That workflow connects your GitHub repo to Supabase, tracks migrations in version control, and creates preview branches automatically when you open a pull request. It works well for teams that manage their database schema as code. But it requires a GitHub connection, which rules out anyone who doesn't work that way.

Branching 2.0 removed that requirement. You create a branch from the dashboard, make changes using the SQL Editor or Table Editor, review a schema diff, and merge. No git configuration required. It shipped behind a feature preview. Today, that preview is gone.

Branching without Git is on by default for every project. It adds a second path for developers who want to iterate on their schema without setting up a Git integration. Both approaches are fully supported, and you can switch between them or use them together. If you're already using git-based branching, nothing changes.

Two ways to branch

Branching without Git

Create branches directly from the Supabase Dashboard. Your branch gets its own Postgres instance with your current production schema. Make changes, preview the diff, and merge. The whole workflow stays inside Supabase.

Choose this when:

  • You're prototyping schema changes and want fast iteration
  • Your team manages the database primarily through the dashboard
  • You're working with AI tools that create and manage branches programmatically
  • You want to try branching without any upfront configuration

Git-based branching

Connect a GitHub repo to your Supabase project. Migrations live in version control. Branches are created automatically when you open a pull request and cleaned up when the PR is closed.

Choose this when:

  • Your team already manages database migrations in git
  • You want schema changes reviewed as part of your pull request workflow
  • You need an audit trail of every migration in version control
  • You prefer an infrastructure-as-code approach to database management

You can start with dashboard branching and add a git integration later when your workflow demands it. The two approaches use the same underlying infrastructure.

How it works

1. Create a branch

Open your project in the Supabase Dashboard and click "Create Branch." Pick a name. Your branch spins up with your current production schema.

2. Make changes

Use the branch like any Supabase project. Add tables, modify columns, update RLS policies, change functions. Every schema change you make in the SQL Editor or Table Editor is tracked.

3. Review the diff

When you're ready to merge, Supabase generates a migration diff showing exactly what changed between your branch and production. This diff is powered by pg-delta, our new schema diffing engine.

4. Merge

Review the generated migration, confirm, and merge. Your schema changes are applied to production.

pg-delta: a new diffing engine

The merge experience depends on accurate schema diffs. We built pg-delta from scratch inside pg-toolbelt to handle the full range of Postgres objects: tables, columns, RLS policies, functions, triggers, indexes, and extensions.

When you merge a branch, pg-delta compares the two schemas and generates the correct migration statements. It replaces migra as the default diffing engine for dashboard branching, with better coverage of Postgres-specific DDL.

pg-delta is also available in the Supabase CLI behind a flag for the diff command if you want to try it locally.

pg-delta is alpha software. If you discover any bugs related to diff review, please file a GitHub issue to help us improve the tooling.

Built for AI workflows

Every branch created through the Supabase MCP server uses dashboard branching automatically. When an AI tool needs to iterate on your database schema, it can create a branch, make changes, and merge, all without touching git. The branch exists for as long as the agent needs it and gets cleaned up when the work is done.

Getting started

Branching is available now in your dashboard.

If you're using the git-based workflow today, nothing changes. Your existing setup continues to work. Dashboard branching is the new default for new projects and for users who haven't configured a git integration.

Today we are launching the OSSCAR Index: the Open Source Supabase Commit Analytical Ranking. A quarterly ranking of the fastest-growing open source organizations, measured with a transparent, reproducible methodology. The site, the data, and the scoring code are all open source. The first edition covers Q1 2026 and is live now.

Open source has a ranking problem.

Most "top open source" lists rank by raw totals: stars, downloads, contributors. Those are real signals, and they accumulate for good reasons. They also tell you who was big yesterday, not who is growing today. The list of fastest-growing open source projects looks nothing like the list of largest ones, and right now there is no good way to find it.

We've been working with >commit on creating the definitive ranking of open-source projects.

What stood out in Q1 2026#

A few observations from this quarter's data:

  • Openclaw was the breakout story of the quarter. It crossed the Scaling threshold by 236 stars on January 1 and finished the quarter at 365,000. It went from 29 contributors to 1,383, and from zero package downloads to 16.7 million. Growth like that almost never happens at this scale. It is one of the few projects in either division where every signal compounded at once.
  • AI agents dominate Emerging. The majority of the top 10 Emerging projects are autonomous agent frameworks, AI-native developer tools, or AI-assisted personal workflows. Paperclip took the #1 Emerging spot, a small team building an autonomous business in the open with contributor counts that grew faster than almost anyone else this quarter.
  • Not everything in the top is AI. Craft Docs, a productivity tool often described as a Notion alternative, came in at #3 Emerging on the back of 768,000 new npm downloads. npmx, a fast browser for the npm registry, picked up 237 new contributors and ranked #7. In Scaling, the Mantine UI library and the Free Ebook Foundation (the project behind Project Gutenberg) both made the top 100 on contributor growth alone. The methodology surfaces real momentum wherever it shows up, including in categories that have been quietly compounding for years.
  • The rankings are genuinely global. Tsinghua University's MAIC, Sipeed (an AIoT hardware platform), Tencent Connect, DingTalk-Real-AI, and BIT-DataLab all appear in the top 100 across both divisions. Most "top open source" lists implicitly rank by signals visible to Western package registries and English-language attention. OSSCAR looks globally.
  • Scaling is harder than Emerging. The bar to show up in the Scaling division is different. You need to already be large, and then grow faster than other large projects. Outside Openclaw, most of the Scaling top 10 grew at multiples between 0.5x and 5x. Modest in percentage terms, but on much larger absolute numbers. Every name in the Scaling top 10 is a project with real production users.
  • A small "Claw" cluster has formed. Openclaw at #1 Scaling, ZeroClaw Labs at #2 Emerging, NullClaw at #15 Emerging, and a GoClaw fork already in the wild. Three months ago, none of these names existed.

What it measures#

The index ranks GitHub organizations by the rate at which their communities are growing, across three signals:

  • Net new GitHub stars
  • Unique contributors
  • Package downloads from npm, PyPI, and Cargo

Each signal is normalized within a division so a 200-person team and a five-person team can be compared fairly. The three normalized scores are then combined into a single composite using an L² norm (the square root of the sum of squares). The L² norm rewards standout growth on a single signal vs more balanced growth across the board, and also doesn't penalize too much projects that are missing a specific metric, such as a library without a published package, for example.

The OSSCAR Index focuses on growth, not size. A project with 800 stars that doubled in a quarter can outrank a project with 80,000 stars that added 5%.

Two divisions#

Ranking a new AI agent framework against Kubernetes is not useful. So the index splits organizations into two independent leaderboards based on their star count at the start of the quarter:

  • Emerging: fewer than 1,000 stars at quarter-start
  • Scaling: 1,000 stars or more at quarter-start

Divisions lock at quarter-start. Cross the threshold mid-quarter and you still compete in Emerging that cycle. This keeps the peer group fair and prevents projects from gaming which division they sit in.

How scoring works#

The score answers a simple question: how much faster is this project growing this quarter than its peers?

For each project we look at three things over the course of the quarter: how many new GitHub stars it picked up, how many new contributors showed up, and how many more package downloads it saw. Each of those gets compared against everyone else in the same division and turned into a number from 0 to 100. Combine them with an L² norm (the square root of the sum of squares) and you get a composite out of ~173.

A few things worth knowing:

  • Small bases do not get a free ride. A project that goes from 2 stars to 20 is not treated as 10x growth. Minimum thresholds keep tiny numbers from producing absurd rates.
  • Exceptional growth stands out. Being truly outstanding on a single signal now beats being merely good on all three. A project that goes huge on stars but has no package downloads can still top a well-rounded peer. We want breakout winners to be visible.
  • Missing signals do not hurt you. A project with no published npm or PyPI package is scored only on the signals that apply to it, and if those signals are growing fast, it can still top the ranking. That's by design. We want to surface outliers wherever they show up, and as we add more signals in future releases, no project should be penalized for the metrics it doesn't have.
  • No decline. If a signal went down over the quarter, it does not count against you. We rank growth, not loss.

The full methodology is on the site. The site itself, the data pipeline, and the scoring code are all on GitHub: commitvc/osscar. If you think a weighting is wrong, a data source is missing, or a division boundary should move, propose it. Read the code, open an issue, send a pull request. We mean it.

Why we are doing this#

Supabase is an open source company. We run on the open source ecosystem: Postgres, PostgREST, pg_vector, Deno, and dozens more tools. We want that ecosystem to be healthy, visible, and legible to developers, customers, and investors who are trying to find what is working. A good index helps new projects get discovered. Discovery helps contributors show up. Contributors ship features. Features create users. That flywheel is how open source compounds.

For the ranked projects#

If you appear in the Q1 2026 OSSCAR Index: congratulations. You can download a badge to promote your entry in the list from your entry on the website.

If you think you should be ranked and are not, check the methodology page first. The most common reasons:

  • You are a personal account, not an organization
  • Your signal volume falls below the padding threshold
  • Your growth rate was flat or negative this quarter

We update quarterly. Q2 2026 data collection is already underway.

What's next#

Three things on the near-term roadmap:

  1. More package managers. Go modules, Rust crates beyond the current coverage, and a better story for projects that distribute via container images.
  2. A clearer RFC process for methodology changes. Today we review proposals and merge what makes sense. By the end of 2026 we want a public RFC process so that weighting changes, new signals, and division boundaries have a predictable path from idea to merged.
  3. Historical rankings. The first index is a snapshot. The second will be a trend. By the fourth quarter, we will have a picture of which projects sustain growth and which flash and fade.

Supabase is now certified to ISO/IEC 27001:2022. The certificate covers our information security management system across the entire platform, including Database, Auth, Storage, Realtime, Edge Functions, and the Data API.

What ISO 27001 is

ISO/IEC 27001:2022 is the international standard for information security management systems, also known as an ISMS. An ISMS is the collection of policies, processes, and controls a company uses to manage risk to the information it holds. The standard defines what an ISMS has to cover, how it has to be documented, and how it has to be maintained.

Certification comes from an accredited third-party auditor. They review the documentation, test the controls, and decide whether the standard has been met. A certificate is valid for three years, with a surveillance audit every year in between, and the ISMS has to keep running the whole time. Controls have to keep working. If the system drifts, the certificate goes away.

How it relates to SOC 2

SOC 2 and ISO 27001 cover a lot of the same ground. Both evaluate how a company protects customer data. Both look at access controls, change management, incident response, and business continuity. A large share of the evidence we already had from SOC 2 mapped cleanly to ISO 27001 controls.

Which one you need depends on where you are:

  • SOC 2 is a report written by your auditor describing how your controls operated over a period of time. It is widely accepted in North America.
  • ISO 27001 is a certificate confirming that your ISMS meets an international standard. It is widely accepted in Europe, Asia, and the public sector.

Some teams need one. Some need both.

What the audit looked like

Certification happens in two stages. Stage one is a documentation review. The auditor reads your policies, risk assessments, and statement of applicability, then decides whether the ISMS is ready to be tested. Stage two is the audit itself. The auditor interviews staff, samples evidence, and tests whether controls work the way you say they do.

Preparing for an audit is a good procedural exercise:

  • Writing and formalizing policies that had previously existed informally
  • Documenting risk assessments properly
  • Running internal audits
  • Selecting an auditor
  • Mapping SOC 2 controls to the ISO 27001 Annex A list so we were not collecting the same evidence twice

What it means for you

If you are on a Team or Enterprise plan, request the ISO 27001 certificate from your dashboard. That is the document your procurement and security teams will ask for.

If a vendor review required ISO 27001 and blocked you from building on Supabase, you are no longer blocked. If a deal has been waiting on this, talk to your account team.

What's next

ISO 27001 is one piece of a broader security and compliance roadmap. We already support SOC2, of course. We already support HIPAA for teams handling protected health information.

If your team has a specific compliance requirement you need from Supabase, tell us. The work we prioritize is shaped by what developers ask us for.

Supabase hits 100,000 GitHub stars. A reflection on community, open source, and what got us here.

A look at recent ISP and government-directed blocks of Supabase domains in three regions—what triggered them, how we worked with authorities and customers to restore access, and what multi-tenant platforms can do to prepare.

Introduced rate limits on recursive/nested Edge Functions calls within your project. Rate limiting applies to outbound fetch() calls made by Edge Functions to other Edge Functions, including direct recursion, function chaining, circular calls, and fan-out patterns.

Rate limit budget: Each request chain has a minimum budget of 5,000 requests per minute. Inbound requests and external API calls are not affected.

Why introduced: Recursive function calls were causing increased response times across multiple regions. Based on metrics, the rate limit affects only 0.4% of projects. A guide on avoiding rate limits is available in the docs.

Supabase Pro users can now send their Supabase logs to their own logging backend, enabling them to debug in the same place as the rest of their stack.

Last Checked
15h ago
Latest
0.1
Tracking since Aug 8, 2023