A production-ready NestJS REST API with multi-tenant architecture, enterprise-grade RBAC, and scalable infrastructure.
Run Way is a comprehensive backend API designed for modern SaaS applications. Built with NestJS 11 and TypeScript, it provides a solid foundation for building multi-tenant applications with role-based access control, secure authentication, and scalable architecture patterns.
After 3+ years of full-stack development, I've learned that the best projects start with a solid foundation. This API demonstrates:
- Enterprise patterns: Multi-tenancy, RBAC, and organization-scoped data isolation
- Modern tooling: Prisma ORM, Redis caching, BullMQ queues, PostgreSQL RLS
- Security first: JWT auth, rate limiting, email verification, row-level security
- Developer experience: TypeScript, Swagger docs, Docker setup, clean architecture
- NestJS 11 - Progressive Node.js framework
- TypeScript - Type-safe development
- Prisma ORM - Modern database toolkit
- PostgreSQL 15 - Robust relational database
- Redis - Caching & session storage
- BullMQ - Job queue for background tasks
- Docker - Containerization
- Row-Level Security (RLS) - Database-level multi-tenancy
- JWT - Access & refresh tokens
- Passport - Authentication strategies
- Bcrypt - Password hashing
- Helmet - Security headers
- Rate Limiting - DDoS protection
- Nodemailer - Email service
- Handlebars - Email templates
- Resend - Email delivery
- Swagger/OpenAPI - API documentation
- ESLint - Code linting
- Prettier - Code formatting
- Jest - Testing framework
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client Applications β
β (Web, Mobile, Desktop Apps) β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API Gateway Layer β
β β’ Authentication (JWT) β
β β’ Rate Limiting β
β β’ Request Validation β
β β’ Organization Context β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Business Logic Layer β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Auth β β Organizationsβ β Projects β β
β β Users β β Roles β β Tasks β β
β β Permissionsβ β Billing β β Billing β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Data Access Layer β
β β’ Prisma ORM β
β β’ Row-Level Security (RLS) β
β β’ Transaction Management β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Infrastructure Layer β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β PostgreSQL β β Redis β β BullMQ β β
β β (Database) β β (Cache) β β (Queue) β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
Multi-Tenancy via RLS
- Database-level isolation using PostgreSQL RLS
- Organization context enforced at query level
- Prevents data leakage between organizations
-
Modular Architecture
- Feature-based modules (auth, users, organizations, etc.)
- Clear separation of concerns
- Easy to scale and maintain
-
Permission-Based Access Control
- Fine-grained permissions
- Organization-scoped permissions
- Dynamic role-permission assignments
-
Queue-Based Processing
- Async email sending via BullMQ
- Scalable background job processing
- Retry mechanisms for failed jobs
- User registration with email verification
- JWT-based authentication (access + refresh tokens)
- Password reset flow
- Rate limiting on sensitive endpoints
- Session management
- Create and manage organizations
- Organization membership management
- Member invitations with role assignment
- Organization-scoped data isolation
- Soft delete support
- Create custom roles per organization
- Define granular permissions
- Assign permissions to roles
- Assign roles to users
- Dynamic permission checking
- User profile management
- User CRUD operations
- Soft delete support
- Email verification workflow
- Email verification
- Password reset emails
- Queue-based email processing
- Handlebars email templates
- Resend integration
- Row-Level Security (RLS) in PostgreSQL
- Organization context guards
- Permission-based access control
- Request validation
- Security headers (Helmet)
- CORS configuration
- CSRF protection
- Node.js (v18 or higher)
- pnpm (or npm/yarn)
- Docker and Docker Compose
- PostgreSQL 15 (via Docker)
- Redis (via Docker)
-
Clone the repository
git clone <repository-url> cd run-way
-
Install dependencies
pnpm install
-
Set up environment variables
Create a
.envfile in the root directory:# Application APP_NAME=Run Way PORT=3000 FRONTEND_URL=http://localhost:3000 # Database DATABASE_HOST=localhost DATABASE_PORT=5432 DATABASE_USER=app_user DATABASE_PASSWORD=app_password DATABASE_NAME=mydatabase # JWT JWT_SECRET=your-secret-key-change-in-production JWT_EXPIRE_IN=3600 JWT_REFRESH_SECRET=your-refresh-secret-key-change-in-production JWT_REFRESH_EXPIRE_IN=604800 # Redis REDIS_HOST=localhost REDIS_PORT=6379 # Email (Resend) RESEND_API_KEY=your-resend-api-key FROM_NAME=Run Way FROM_EMAIL=noreply@example.com VERIFICATION_DELAY=5000
-
Start Docker services
docker-compose up -d
This starts:
- PostgreSQL (port 5432)
- Shadow PostgreSQL (port 5433)
- Redis (port 6379)
- Adminer (port 8080) - Database admin UI
-
Run database migrations
pnpm prisma migrate deploy
-
Generate Prisma Client
pnpm prisma generate
-
Start the development server
pnpm run start:dev
The API will be available at http://localhost:3000
- API: http://localhost:3000
- Swagger Documentation: http://localhost:3000/api (if configured)
- Adminer (Database UI): http://localhost:8080
- System: PostgreSQL
- Server: db
- Username: app_user
- Password: app_password
- Database: mydatabase
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /auth/register |
Register a new user | β |
| POST | /auth/login |
Login user | β |
| GET | /auth/profile |
Get current user profile | β |
| POST | /auth/refresh-token |
Refresh access token | β |
| POST | /auth/forget-password |
Request password reset | β |
| POST | /auth/reset-password |
Reset password with token | β |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /users |
List all users | β |
| GET | /users/:id |
Get user by ID | β |
| POST | /users/create |
Create a new user | β |
| DELETE | /users/:id |
Delete user | β |
| Method | Endpoint | Description | Auth Required | Permission Required |
|---|---|---|---|---|
| POST | /organizations |
Create organization | β | - |
| GET | /organizations/:id |
Get organization by ID | β | ORGANIZATIONS.READ |
| GET | /organizations/user/organizations |
Get user's organizations | β | ORGANIZATIONS.READ |
| DELETE | /organizations/:id |
Delete organization | β | ORGANIZATIONS.DELETE |
| POST | /organizations/invite-member |
Invite member to organization | β | ORGANIZATIONS.INVITE_MEMBER |
| GET | /organizations/:id/members |
Get organization members | β | ORGANIZATIONS.GET_MEMBERS |
| Method | Endpoint | Description | Auth Required | Permission Required |
|---|---|---|---|---|
| GET | /roles |
Get all roles | β | ROLES.READ |
| POST | /roles |
Create role | β | ROLES.CREATE |
| PATCH | /roles/:id |
Update role | β | ROLES.UPDATE |
| DELETE | /roles/:id |
Delete role | β | ROLES.DELETE |
| Method | Endpoint | Description | Auth Required | Permission Required |
|---|---|---|---|---|
| GET | /permissions |
Get all permissions | β | PERMISSIONS.READ |
| POST | /permissions |
Create permission | β | PERMISSIONS.CREATE |
| PUT | /permissions/:id |
Update permission | β | PERMISSIONS.UPDATE |
| DELETE | /permissions/:id |
Delete permission | β | PERMISSIONS.DELETE |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /email/verify |
Verify email with token | β |
| POST | /email/resend-email-verification |
Resend verification email | β |
- User: User accounts with email verification
- Organization: Multi-tenant organizations
- OrganizationMember: User-organization relationships with status
- Role: Organization-scoped roles
- Permission: Organization-scoped permissions
- RolePermission: Many-to-many relationship between roles and permissions
- OrganizationMemberRole: Many-to-many relationship between members and roles
- EmailVerification: Email verification tokens
- PasswordReset: Password reset tokens
- Row-Level Security (RLS): Database-level security for multi-tenant data isolation
- Soft Delete:
deletedAtfields on User, Organization, OrganizationMember, and Role - Indexes: Optimized indexes on foreign keys and frequently queried fields
- β Row-Level Security (RLS): Database-level security for multi-tenant data isolation
- β JWT Authentication: Secure token-based authentication with refresh tokens
- β Rate Limiting: Protection against brute force attacks
- β Email Verification: Required for account activation
- β Password Hashing: Bcrypt for secure password storage
- β Helmet: Security headers
- β CORS: Configurable cross-origin resource sharing
- β Input Validation: class-validator for request validation
- β Organization Context Guards: Ensure users can only access their organization's data
- β Permission Guards: Fine-grained access control
# Development
pnpm run start:dev # Start in watch mode
pnpm run start:debug # Start in debug mode
# Production
pnpm run build # Build for production
pnpm run start:prod # Start production server
# Database
pnpm prisma migrate dev # Create and apply migration
pnpm prisma generate # Generate Prisma Client
pnpm prisma studio # Open Prisma Studio
# Code Quality
pnpm run lint # Run ESLint
pnpm run format # Format code with Prettier
# Testing
pnpm run test # Run unit tests
pnpm run test:e2e # Run E2E tests
pnpm run test:cov # Run tests with coverageThe docker-compose.yaml includes:
- PostgreSQL: Main database (port 5432)
- Shadow PostgreSQL: For Prisma migrations (port 5433)
- Redis: Cache and queue (port 6379)
- Adminer: Database administration UI (port 8080)
- Create a feature branch
- Make your changes
- Add tests if applicable
- Ensure all tests pass
- Submit a pull request
UNLICENSED - Private project
Last updated: January 2025