nestjs-backend-patterns · git:20260831.84892c0 · 2026-08-31 · sha256 38a1c7dcb820944c
nestjs-backend-patterns git:20260831.84892c0A
Immutable. This exact content never changes and is served at /api/v1/blob/38a1c7dcb820944c.
---
name: nestjs-backend-patterns
description: NestJS backend architecture patterns for multi-tenant SaaS applications. Use when integrating third-party services/APIs into NestJS, setting up Prisma or ZenStack, implementing multitenancy patterns, building authentication/authorization, creating provider patterns for external services, applying access control with RBAC or policies, or handling database connection and repository patterns.
---
# NestJS Backend Architecture Patterns
Patterns for building scalable, maintainable NestJS backends in an Nx monorepo.
## Activation scope
This skill activates **per-module during Stage B** of the SaaS bootstrap. `saas-workspace-initializer` may scaffold thin tenant/auth primitives in the Stage A foundation, but full provider-pattern integrations, multitenancy enforcement, and Prisma/ZenStack policy work happen in dedicated Stage B sessions driven by individual roadmap items. Pull this skill in when implementing one such item, not to retrofit an entire backend.
## Core Principle: Provider Pattern for External Services
All third-party integrations follow the same provider pattern:
```typescript
// 1. Create a provider factory
export const ThirdPartyClientProvider = {
provide: 'THIRD_PARTY_CLIENT',
useFactory: (configService: ConfigService) => {
return new ThirdPartySDK(configService.get('THIRD_PARTY_API_KEY'));
},
inject: [ConfigService],
};
// 2. Create a service that wraps the client
@Injectable()
export class ThirdPartyService {
constructor(@Inject('THIRD_PARTY_CLIENT') private client: ThirdPartySDK) {}
async doSomething() {
return this.client.operation();
}
}
// 3. Create a module that exports the service
@Module({
imports: [ConfigModule],
providers: [ThirdPartyClientProvider, ThirdPartyService],
exports: [ThirdPartyService],
})
export class ThirdPartyModule {}
```
## Quick Reference
| Pattern | Use Case | Reference |
| ------------------ | ----------------------------------- | ------------------------------------------------------------------- |
| Provider Pattern | Third-party API integration | [third-party-integration.md](references/third-party-integration.md) |
| Multitenancy | Shared schema with tenant isolation | [multitenancy.md](references/multitenancy.md) |
| Prisma + ZenStack | ORM with declarative access control | [prisma-zenstack.md](references/prisma-zenstack.md) |
| RBAC | Role-based authorization | [authorization.md](references/authorization.md) |
| JWT Authentication | Stateless auth with Passport | [authentication.md](references/authentication.md) |
## Third-Party Integration Pattern
### Step 1: Provider Factory
```typescript
// libs/shared/payments/src/lib/payment-client.provider.ts
import { ConfigService } from '@nestjs/config';
export const PaymentClientProvider = {
provide: 'PAYMENT_CLIENT',
useFactory: (config: ConfigService) => {
const provider = config.get('PAYMENT_PROVIDER'); // 'stripe', 'paddle', etc.
const apiKey = config.get('PAYMENT_API_KEY');
// Factory returns appropriate client based on config
switch (provider) {
case 'stripe':
return new StripeClient(apiKey);
case 'paddle':
return new PaddleClient(apiKey);
default:
throw new Error(`Unknown payment provider: ${provider}`);
}
},
inject: [ConfigService],
};
```
### Step 2: Abstract Service Interface
```typescript
// libs/shared/payments/src/lib/payment.interface.ts
export interface PaymentClient {
createCustomer(data: CreateCustomerDto): Promise<Customer>;
createSubscription(data: CreateSubscriptionDto): Promise<Subscription>;
cancelSubscription(id: string): Promise<void>;
handleWebhook(payload: Buffer, signature: string): Promise<WebhookEvent>;
}
```
### Step 3: Service Implementation
```typescript
// libs/shared/payments/src/lib/payment.service.ts
@Injectable()
export class PaymentService {
constructor(@Inject('PAYMENT_CLIENT') private client: PaymentClient) {}
async createCustomer(dto: CreateCustomerDto): Promise<Customer> {
return this.client.createCustomer(dto);
}
async createSubscription(dto: CreateSubscriptionDto): Promise<Subscription> {
return this.client.createSubscription(dto);
}
}
```
## Multitenancy Pattern (Shared Schema)
```typescript
// Context-aware Prisma service using CLS (Continuation Local Storage)
@Injectable()
export class TenantAwarePrismaService {
constructor(
private prisma: PrismaService,
private cls: ClsService,
) {}
get client() {
const tenantId = this.cls.get('tenantId');
if (!tenantId) {
throw new UnauthorizedException('No tenant context');
}
// Return enhanced client with tenant filter
return enhance(this.prisma, { user: { tenantId } });
}
}
```
## Module Organization
```
libs/
├── shared/
│ ├── prisma-client/ # Prisma + ZenStack setup
│ │ ├── prisma.service.ts
│ │ ├── enhanced-prisma.service.ts
│ │ └── prisma-client.module.ts
│ ├── auth/ # Authentication infrastructure
│ │ ├── strategies/
│ │ │ └── jwt.strategy.ts
│ │ ├── guards/
│ │ │ ├── jwt-auth.guard.ts
│ │ │ └── roles.guard.ts
│ │ └── auth.module.ts
│ └── [service-name]/ # Third-party integrations
│ ├── [name]-client.provider.ts
│ ├── [name].service.ts
│ └── [name].module.ts
└── [domain]/
└── feature-api/
├── controllers/
├── dto/
└── [domain].module.ts
```
## Decision Matrix
| Need | Pattern | Reference |
| --------------------- | --------------------------- | ------------------------------------------------------------------- |
| Payment processing | Provider pattern | [third-party-integration.md](references/third-party-integration.md) |
| External auth (OAuth) | Provider pattern + Passport | [authentication.md](references/authentication.md) |
| Email service | Provider pattern | [third-party-integration.md](references/third-party-integration.md) |
| File storage | Provider pattern | [third-party-integration.md](references/third-party-integration.md) |
| Tenant isolation | ZenStack policies | [multitenancy.md](references/multitenancy.md) |
| Role-based access | Guards + decorators | [authorization.md](references/authorization.md) |
## References
Load these for detailed implementation guidance:
- [third-party-integration.md](references/third-party-integration.md) - Generic pattern for any external service
- [multitenancy.md](references/multitenancy.md) - Multi-tenant architecture patterns
- [prisma-zenstack.md](references/prisma-zenstack.md) - ORM setup with access policies
- [authorization.md](references/authorization.md) - RBAC and permission patterns
- [authentication.md](references/authentication.md) - JWT and OAuth patterns