2-how-to-build-scalable-apis-with-nestjs-and-postgresql.html

How to Build Scalable APIs with NestJS and PostgreSQL

Creating a scalable API is a fundamental requirement for modern web applications. With the rise in demand for efficient data handling and performance, using a robust framework and a reliable database becomes essential. In this article, we’ll explore how to build scalable APIs using NestJS, a progressive Node.js framework, and PostgreSQL, an advanced open-source relational database.

What is NestJS?

NestJS is a versatile and powerful Node.js framework that leverages TypeScript to create highly testable, scalable, and maintainable applications. It is built around the concepts of modularity and dependency injection, making it an excellent choice for building APIs.

Key Features of NestJS:

  • Modular Architecture: Supports organizing code into modules, which enhances maintainability.
  • Dependency Injection: Facilitates better testing and code management.
  • Asynchronous Programming: Built-in support for asynchronous programming using async/await.
  • Extensive Ecosystem: Integrates easily with various libraries and tools.

Why Use PostgreSQL?

PostgreSQL is a powerful, open-source object-relational database known for its robustness, performance, and SQL compliance. It is ideal for applications requiring complex queries and data integrity.

Benefits of PostgreSQL:

  • ACID Compliance: Ensures reliable transactions.
  • Rich Data Types: Supports JSON, XML, and custom data types.
  • Scalability: Handles a large volume of data and high concurrency effectively.

Setting Up Your Development Environment

Prerequisites:

  • Node.js installed (preferably version 14 or above)
  • PostgreSQL installed and running
  • Basic knowledge of TypeScript and RESTful APIs

Step 1: Creating a New NestJS Project

To start, install the NestJS CLI globally if you haven't already:

npm install -g @nestjs/cli

Now, create a new NestJS project:

nest new scalable-api
cd scalable-api

Step 2: Install Required Packages

Next, you need to install the necessary packages for PostgreSQL and TypeORM, which NestJS uses to interact with databases:

npm install @nestjs/typeorm typeorm pg

Step 3: Configure PostgreSQL Connection

Open the app.module.ts file and set up the TypeORM connection to PostgreSQL:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'your_username',
      password: 'your_password',
      database: 'your_database',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Step 4: Create an Entity

Entities represent tables in your PostgreSQL database. Let’s create a simple User entity.

  1. Create a new directory src/users and a file user.entity.ts inside it:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;
}

Step 5: Create a Service and Controller

Next, create a service and controller for handling user operations.

  1. Generate a service:
nest generate service users/users
  1. Implement user service logic in users.service.ts:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  create(user: User): Promise<User> {
    return this.usersRepository.save(user);
  }

  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  findOne(id: number): Promise<User> {
    return this.usersRepository.findOneBy({ id });
  }
}
  1. Create a controller:
nest generate controller users/users
  1. Implement user controller logic in users.controller.ts:
import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './user.entity';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  create(@Body() user: User) {
    return this.usersService.create(user);
  }

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }
}

Step 6: Testing the API

Now that everything is set up, you can run the application:

npm run start

Use Postman or any API testing tool to test your endpoints:

  • POST http://localhost:3000/users with a JSON body like: json { "name": "John Doe", "email": "john.doe@example.com" }
  • GET http://localhost:3000/users to retrieve all users.
  • GET http://localhost:3000/users/1 to retrieve a specific user.

Best Practices for Building Scalable APIs

  1. Use Pagination: For endpoints returning large datasets, implement pagination to improve performance.
  2. Caching: Utilize caching strategies to reduce database load.
  3. Error Handling: Implement global and local exception filters for a better user experience.
  4. Rate Limiting: Protect your API from abuse by implementing rate limiting.

Conclusion

Building scalable APIs with NestJS and PostgreSQL is not only efficient but also enjoyable due to the framework's elegant structure and the database's reliability. By following the steps outlined above, you can create a robust API capable of handling significant loads while ensuring data integrity and performance. Embrace the power of NestJS and PostgreSQL in your next project, and watch your applications thrive!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.