Does NestJS Work With Supabase?
NestJS and Supabase work excellently together, with NestJS providing the backend framework and Supabase handling authentication, database, and realtime features.
Quick Facts
How NestJS Works With Supabase
NestJS integrates seamlessly with Supabase through the official Supabase JavaScript client library. You can use Supabase's PostgreSQL database as your primary data store, leverage its built-in auth for user management, and tap into realtime subscriptions for WebSocket functionality. The typical architecture involves installing `@supabase/supabase-js`, initializing a Supabase client in a NestJS service, and using it for database queries, auth token verification, and realtime listeners. NestJS guards can validate Supabase JWT tokens, and dependency injection makes the Supabase client available across your application cleanly. Many developers use an ORM like Prisma or TypeORM on top of Supabase's PostgreSQL for type safety and migrations, though direct client usage works fine for simpler applications. The developer experience is smooth because both tools favor TypeScript and have good async/await support.
Best Use Cases
Quick Setup
npm install @supabase/supabase-js// supabase.service.ts
import { Injectable } from '@nestjs/common';
import { createClient } from '@supabase/supabase-js';
@Injectable()
export class SupabaseService {
private supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_ANON_KEY
);
async getUserById(id: string) {
const { data, error } = await this.supabase
.from('users')
.select('*')
.eq('id', id)
.single();
if (error) throw error;
return data;
}
async verifyToken(token: string) {
const { data, error } = await this.supabase.auth.getUser(token);
if (error) throw error;
return data.user;
}
}
// users.controller.ts
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { SupabaseService } from './supabase.service';
@Controller('users')
export class UsersController {
constructor(private supabase: SupabaseService) {}
@Get(':id')
async getUser(@Param('id') id: string) {
return this.supabase.getUserById(id);
}
}Known Issues & Gotchas
JWT token expiration requires manual refresh logic in NestJS guards
Fix: Implement a refresh token strategy in your auth guard or use Supabase's session management with automatic token refresh
Row Level Security (RLS) policies must be defined in Supabase; bypassed queries need service role key, which shouldn't be exposed
Fix: Keep service role keys in environment variables, only used server-side. Use user-level clients in browser. Always enable RLS for security
Realtime subscriptions require explicit configuration and don't work with all query types
Fix: Use Supabase's documented realtime-enabled tables and test subscriptions in development before production deployment
TypeScript types for Supabase queries require manual generation or type inference setup
Fix: Use Supabase's TypeScript client generation tool or pair with Prisma for auto-generated types from your schema
Alternatives
- •Firebase with NestJS - Google's managed backend with similar auth/realtime, but vendor lock-in and higher costs at scale
- •NestJS with PostgreSQL + Prisma + Auth0 - More granular control, better for complex schemas, but requires managing infrastructure separately
- •NestJS with MongoDB + Auth0 - NoSQL alternative for unstructured data, but loses Supabase's realtime and PostgreSQL benefits
Resources
Related Compatibility Guides
Explore more compatibility guides