Skip to main content

Which package to use

还没翻译译自英文(supabase.com)本页 21 段都还没译

When you use Supabase from JavaScript on the server, there are three packages to choose from. They are not alternatives to each other — @supabase/ssr and @supabase/server both build on top of supabase-js and solve different problems. This guide helps you pick the right one.

Note

These are JavaScript packages, not separate language SDKs. If you're looking for the client library for another language (Python, Swift, Kotlin, etc.), see the client library references.

Which package to use

The quickest way to decide is by how the user's identity reaches your code:

  • The session lives in cookies (an SSR framework like Next.js or SvelteKit) → use @supabase/ssr.
  • Auth arrives per request in headers (Authorization: Bearer <jwt>) → use @supabase/server.
  • You want the base client, or you're handling auth yourself → use @supabase/supabase-js directly.
PackageUse it whenRuns inAuth model
@supabase/supabase-jsYou want the base client, or you manage auth yourselfBrowser and serverYou wire up auth
@supabase/ssrUser sessions are stored in cookiesSSR frameworks (Next.js, SvelteKit, TanStack Start)Cookie-based sessions, with refresh-token rotation
@supabase/serverAuth arrives per request in headersEdge Functions, Workers, Vercel, Bun, and framework APIs (Hono, H3, Elysia, NestJS)Stateless Bearer JWT + apikey

@supabase/supabase-js

The isomorphic base client. @supabase/ssr and @supabase/server both wrap it — reach for supabase-js directly when you don't need either wrapper's auth handling.

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_PUBLISHABLE_KEY!)

@supabase/ssr

For SSR frameworks that store the user's session in cookies. It reads and writes session cookies and handles refresh-token rotation, so the same user and session are available on both the client and the server.

import { createServerClient } from '@supabase/ssr'

const supabase = createServerClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_PUBLISHABLE_KEY!,
  {
    cookies: {
      getAll() {
        // return the request's cookies
      },
      setAll(cookiesToSet) {
        // write cookies back on the response
      },
    },
  }
)

See the server-side rendering guide for framework-specific setup.

@supabase/server

For stateless, header-based auth in backend runtimes — Edge Functions, Workers, and framework APIs. You declare who may call an endpoint and receive a ready-to-use context (a caller-scoped client that respects RLS, plus an admin client). It verifies JWTs and resolves the new API keys (SUPABASE_PUBLISHABLE_KEYS / SUPABASE_SECRET_KEYS) for you.

import { withSupabase } from '@supabase/server'

export default {
  fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
    // ctx.supabase is scoped to the caller and respects RLS
    const { data } = await ctx.supabase.from('todos').select()
    return Response.json(data)
  }),
}

See the @supabase/server reference for the full API.

@supabase/server is also the package for MCP servers. Its withOAuthProtectedResource middleware handles OAuth discovery for MCP clients, and composed with withSupabase({ auth: 'user' }) every tool call runs as the signed-in user. See Deploy MCP servers.

Note

@supabase/ssr and @supabase/server coexist and are not replacements for each other, and @supabase/ssr is not deprecated. Pick based on where your code runs and how auth reaches it, using the table above.

Advanced: Combining @supabase/server and @supabase/ssr

In a cookie-based framework you can compose the two — let @supabase/ssr own the cookie session lifecycle and hand the resolved token to @supabase/server's primitives. This requires more setup, and deeper first-party integration is on the roadmap. See the @supabase/server SSR frameworks guide.

Next steps