Careeroza
Real World Example
From ShopEase to a Real Company
The architecture you built is close to what real Indian e-commerce and D2C companies (boAt, Mamaearth, Lenskart-style brands on custom stacks) run in their first years: a modular NestJS monolith on PostgreSQL and Redis, a Next.js storefront, a payment gateway with webhooks, queues for notifications and a few cron jobs. As traffic grows, the usual next steps are:
- Read replicas for the database and a CDN in front of public GET endpoints.
- Splitting the busiest or most independent module (notifications, search) into its own service with
@nestjs/microservicesand Kafka/RabbitMQ. - A search engine (Elasticsearch / OpenSearch / Typesense) fed by product events.
- OpenTelemetry tracing across services.
src/app.module.ts (final)
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true, cache: true, load: [databaseConfig, paymentsConfig], validate }),
LoggerModule.forRoot({ pinoHttp: { redact: ['req.headers.authorization'] } }),
ThrottlerModule.forRoot([{ name: 'long', ttl: 60_000, limit: 200 }]),
CacheModule.registerAsync({ isGlobal: true, inject: [ConfigService], useFactory: redisCacheFactory }),
BullModule.forRootAsync({ inject: [ConfigService], useFactory: bullFactory }),
ScheduleModule.forRoot(),
PrismaModule,
AuthModule, UsersModule, CategoriesModule, ProductsModule, CartModule,
OrdersModule, PaymentsModule, NotificationsModule, TasksModule, HealthModule,
],
providers: [
{ provide: APP_GUARD, useClass: ThrottlerGuard },
{ provide: APP_GUARD, useClass: JwtAuthGuard },
{ provide: APP_GUARD, useClass: RolesGuard },
{ provide: APP_INTERCEPTOR, useClass: TransformInterceptor },
{ provide: APP_FILTER, useClass: AllExceptionsFilter },
{ provide: APP_PIPE, useValue: new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true, transform: true }) },
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(RequestIdMiddleware).forRoutes('{*splat}');
}
}