A multi-tenant microservices architecture built with Express.js, PostgreSQL, and Docker. The system provides isolated tenant environments with a central gateway for authentication and routing.
┌─────────────┐
│ Client │
└──────┬──────┘
│
▼ :4000
┌─────────────┐
│ Gateway │──── OAuth2 Authentication
│ Service │──── JWT Token Generation
│ │──── Tenant Routing
└──────┬──────┘
│
┌────┴────┐
│ │
▼ :4001 ▼ :4002
┌──────┐ ┌──────┐
│Tenant│ │Tenant│
│ 1 │ │ 2 │
└──────┘ └──────┘
- Gateway Service (Port 4000): Entry point with OAuth2 authentication, user management, and request routing
- Tenant Services (Ports 4001, 4002): Business logic and resources for each tenant
- PostgreSQL Databases: Separate database for gateway and each tenant
- OAuth2 authentication with JWT tokens
- Multi-tenant architecture with complete isolation
- Tenant-based request routing
- User and API client management
- RESTful API for products and categories
- Health check endpoints
- Comprehensive logging
- Docker containerization
- Docker and Docker Compose
- Git
- Clone the repository:
git clone <repository-url>
cd micro_tenants_test- Start all services:
docker-compose up -d- Check service health:
curl http://localhost:4000/health
curl http://localhost:4001/health
curl http://localhost:4002/healthPOST /auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword",
"firstName": "John",
"lastName": "Doe",
"tenantId": "tenant1"
}POST /auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword"
}POST /auth/refresh
Content-Type: application/json
{
"refreshToken": "your-refresh-token"
}POST /auth/client/register
Content-Type: application/json
{
"name": "My API Client",
"tenantId": "tenant1",
"redirectUris": ["http://localhost:3000/callback"]
}
# Response includes clientId and clientSecret (save these securely!)
{
"clientId": "client_1234567890_abc123",
"clientSecret": "your-generated-secret",
"name": "My API Client",
"tenantId": "tenant1"
}POST /auth/oauth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "client_1234567890_abc123",
"client_secret": "your-generated-secret"
}
# Response
{
"access_token": "jwt-token-for-client",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "api"
}All product endpoints are accessed through the gateway at /api/products. The gateway routes to the appropriate tenant based on the JWT token.
GET /api/products
Authorization: Bearer <jwt-token>GET /api/products/:id
Authorization: Bearer <jwt-token>POST /api/products
Authorization: Bearer <jwt-token>
Content-Type: application/json
{
"name": "Product Name",
"description": "Product description",
"price": 29.99,
"stock": 100,
"sku": "PROD-001",
"categoryId": "category-uuid"
}PUT /api/products/:id
Authorization: Bearer <jwt-token>
Content-Type: application/json
{
"name": "Updated Product Name",
"price": 39.99
}DELETE /api/products/:id
Authorization: Bearer <jwt-token>GET /api/products/categories
Authorization: Bearer <jwt-token>POST /api/products/categories
Authorization: Bearer <jwt-token>
Content-Type: application/json
{
"name": "Electronics",
"description": "Electronic products"
}# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose down
# Rebuild services
docker-compose up --build
# Access service shell
docker-compose exec gateway sh
docker-compose exec tenant1 sh
docker-compose exec tenant2 sh
# Run database migrations
docker-compose exec gateway npm run migrate
docker-compose exec tenant1 npm run migrate
docker-compose exec tenant2 npm run migrateEach service can be configured through environment variables. See .env.example files in each service directory for available options.
Run tests for each service:
docker-compose exec gateway npm test
docker-compose exec tenant1 npm test
docker-compose exec tenant2 npm testThe system is fully containerized. To make changes:
- Modify the code in the respective service directory
- Rebuild the service:
docker-compose up --build <service-name> - Check logs:
docker-compose logs -f <service-name>
- Change JWT_SECRET in production
- Use strong passwords for database
- Enable HTTPS in production
- Implement rate limiting
- Add input validation
- Use environment-specific configurations
MIT