cd..blog

Building Scalable APIs: NestJS, AWS Lambda, & Supabase Integration

const published = "Nov 4, 2025, 10:22 PM";const readTime = 5 min;
nestjsaws lambdasupabasetypescriptapi development
Discover how to integrate NestJS, AWS Lambda, and Supabase to build powerful, scalable, and secure APIs using TypeScript. Learn practical setup, data interaction, and serverless deployment.

Building Scalable APIs: NestJS, AWS Lambda, & Supabase Integration

Modern web development demands robust, scalable, and secure APIs. This post guides you through integrating NestJS, AWS Lambda, and Supabase to build a high-performance API using TypeScript, ready for 2025 and beyond.

Architecture Overview

Our integrated architecture leverages specialized tools for each layer:

  • NestJS: A progressive Node.js framework for building efficient, reliable, and scalable server-side applications. It leverages TypeScript and combines elements of OOP, FP, and FRP to provide a structured development experience.
  • AWS Lambda & API Gateway: AWS Lambda allows you to run code without provisioning or managing servers, executing your NestJS application on demand. API Gateway handles API routing, security, and management, providing a robust serverless backbone.
  • Supabase: An open-source Firebase alternative providing a powerful PostgreSQL database, authentication, storage, and real-time capabilities. It simplifies backend development, letting you focus on your application logic rather than infrastructure.

Setting Up NestJS for Serverless

First, set up a new NestJS project (nest new project-name). To prepare NestJS for AWS Lambda, we'll use @vendia/serverless-express to adapt the Express application instance that NestJS creates.

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';
import * as express from 'express';
import * as serverlessExpress from '@vendia/serverless-express';

let cachedServer: INestApplication;

async function bootstrap(): Promise<INestApplication> {
  if (!cachedServer) {
    const expressApp = express();
    const app = await NestFactory.create(AppModule, new ExpressAdapter(expressApp));
    app.enableCors(); // Configure CORS as needed
    await app.init();
    cachedServer = app;
  }
  return cachedServer;
}

export const handler = async (event: any, context: any) => {
  const app = await bootstrap();
  const server = serverlessExpress({ app: app.getHttpAdapter().getInstance() });
  return server(event, context);
};

This main.ts prepares your NestJS application to run within an AWS Lambda environment, allowing it to efficiently handle HTTP events via an Express adapter.

Integrating Supabase

Supabase provides a powerful JavaScript client. Install it via npm install @supabase/supabase-js.

Next, create a service to interact with your Supabase database. Ensure you've created a "products" table in your Supabase project.

// src/products/products.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { createClient, SupabaseClient } from '@supabase/supabase-js';

@Injectable()
export class ProductsService implements OnModuleInit {
  private supabase: SupabaseClient;

  onModuleInit() {
    // Initialize Supabase client using environment variables for security
    this.supabase = createClient(
      process.env.SUPABASE_URL!,
      process.env.SUPABASE_ANON_KEY!
    );
  }

  async findAllProducts() {
    const { data, error } = await this.supabase
      .from('products')
      .select('*')
      .limit(10);

    if (error) {
      throw new Error(`Failed to fetch products: ${error.message}`);
    }
    return data;
  }

  async createProduct(product: { name: string; price: number }) {
    const { data, error } = await this.supabase
      .from('products')
      .insert([product])
      .select(); // Use .select() to return the inserted data

    if (error) {
      throw new Error(`Failed to create product: ${error.message}`);
    }
    return data?.[0]; // Return the first inserted item
  }
}

We initialize the Supabase client using environment variables (SUPABASE_URL, SUPABASE_ANON_KEY) for secure access and demonstrate basic findAllProducts and createProduct operations within a NestJS service.

Deploying to AWS Lambda with Serverless Framework

To deploy your NestJS application as a serverless function, we'll use the Serverless Framework. Install it globally (npm install -g serverless).

Create a serverless.yml file in your project root:

# serverless.yml
service: nestjs-supabase-api

provider:
  name: aws
  runtime: nodejs20.x # Use the latest LTS runtime
  region: us-east-1
  environment:
    SUPABASE_URL: ${env:SUPABASE_URL}
    SUPABASE_ANON_KEY: ${env:SUPABASE_ANON_KEY}
  iam:
    roleManagedPolicies:
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

plugins:
  - serverless-offline # For local development: npm install serverless-offline
  - serverless-plugin-optimize # For smaller bundle sizes: npm install serverless-plugin-optimize

functions:
  api:
    handler: dist/main.handler # Path to your compiled NestJS handler
    events:
      - http:
          path: /{proxy+}
          method: ANY
          cors: true

This serverless.yml configures AWS Lambda and API Gateway for your NestJS application, routing all requests through the main.handler and securely passing Supabase credentials via environment variables. Remember to set SUPABASE_URL and SUPABASE_ANON_KEY in your deployment environment.

Conclusion

This integration provides a robust, scalable, and cost-effective architecture for modern API development. NestJS offers a structured and maintainable approach to API development, AWS Lambda ensures unparalleled serverless scalability and cost efficiency, and Supabase simplifies database and authentication management, allowing you to build powerful applications with confidence.

By combining these technologies, you can create highly efficient and secure APIs that are easy to develop, deploy, and scale.