Backend Architecture
Overview
The backend is a modular Node.js application built with Express, Prisma ORM, and Firebase authentication. It follows a layered architecture pattern designed for scalability, maintainability, and multi-tenant support.
Architecture Diagram
Core Architecture Components
Application Entry Point
The application initializes through index.js
, which:
- Loads environment variables
- Configures the Express application
- Sets up logging
- Initializes Firebase connection
- Starts the HTTP server
Configuration Layer
Located in the config
directory:
- express-app.config.js: Configures the Express application, middleware, and routes
- firebase.config.js: Initializes Firebase for authentication services
- prisma.config.js: Sets up the Prisma client for database operations
- tenant-aware-pgpool-manager.config.js: Manages database connection pools for multi-tenant support
- winston.config.js: Configures the Winston logging service
Middleware Layer
Key middleware components:
- Authentication Middleware (
auth.middleware.js
): Validates JWT tokens and Firebase authentication - Tenant Middleware (
tenant.middleware.js
): Handles tenant context for multi-tenant operations - Database Middleware (
database.middleware.js
): Manages database connections and transactions - Error Handling (
utils/error.util.js
): Provides centralized error handling - Logging (
utils/logger.js
): Implements application-wide logging
Module Layer
The application's functionality is organized into modular components in the modules
directory:
Core Modules:
- auth: Authentication and authorization mechanisms
- tenant: Multi-tenancy implementation
- tenantRole: Role-based access control
- userManagement: User operations and profile management
Database Modules:
- database: Core database operations
- databaseChart: Chart generation and visualization
- databaseDashboard: Dashboard configuration and management
- databaseQuery: Query execution and management
- databaseTable: Table operations and schema management
- databaseTrigger: Event-driven database triggers
Module Structure: Each module follows a consistent structure:
- Controller (
*.controller.js
): Handles HTTP requests and responses - Service (
*.service.js
): Contains business logic - Routes (
*.v1.routes.js
): Defines API endpoints - Middleware (
*.middleware.js
): Module-specific request processing
Data Access Layer
- Prisma ORM: Object-Relational Mapping for PostgreSQL (used by core, queries, chart, dashboard modules)
prisma/schema.prisma
: Database schema definitionprisma/migrations
: Database migration files
- Node PG: Postgres SQL node client (used by database, databaseTable & databaseTrigger module)
config/tenant-aware-pgpool-manager.config.js
: Manages database connections per tenant/schema.prismautils/postgresql.util.js
: Contains raw database queries used by pg client
- PostgreSQL: Persistent data storage
Utility Layer
Located in the utils
directory:
- Error Handling (
error.util.js
): Custom error classes and error handling functions - Logging (
logger.js
): Logging utility for application events - String Utilities: Functions for string manipulation and validation
- Date Utilities: Date formatting and manipulation
- Security Utilities: Encryption and hashing functions
Scripts
- Database Seeding (
scripts/seed.js
): Initializes database with seed data - Development Tools (
scripts/dev/
): Utilities for development workflows- Module generation templates
- Test data generators
Authentication Flow
- Client submits credentials to Firebase Authentication
- Firebase returns JWT token to client
- Client includes JWT in Authorization header for subsequent requests
- Authentication middleware validates the token
- Tenant middleware establishes tenant context
- Role-based access control enforces permissions
Request Processing Pipeline
- Request received by Express server
- Global middleware processes request:
- Logging
- CORS handling
- Body parsing
- Authentication
- Tenant middleware establishes tenant context
- Route-specific middleware applies:
- Parameter validation
- Resource-specific checks
- Controller processes the request
- Service layer implements business logic
- Prisma client interacts with PostgreSQL database
- Response flows back through the layers
- Error handling middleware catches exceptions
Multi-tenancy Architecture
The system implements a multi-tenant architecture with:
- Tenant Isolation: Each tenant's data is logically separated
- Tenant-Aware Connection Pooling: Optimized database connections per tenant
- Role-Based Access Control: Permissions scoped to tenant contexts
- Tenant Middleware: Automatically applies tenant context to requests
Error Handling Strategy
The application implements a hierarchical error handling approach:
- Custom Error Classes: Extend standard Error for specific scenarios
- Service-Level Error Handling: Business logic validation and error generation
- Controller-Level Error Handling: HTTP-specific error handling
- Global Error Middleware: Catches unhandled errors
- Structured Error Responses: Consistent error format for API clients
Logging Architecture
- Winston Logger: Configured for different environments
- Log Levels: Debug, Info, Warning, Error
- Log Destinations:
- Console (development)
- Files (rotation based on size and retention policy)
- Syslog (production)
- Context Enrichment: Adds request ID, tenant ID, and user information to logs
Security Architecture
- Authentication: Firebase and JWT-based
- Authorization: Role-based access control
- Data Validation: Input validation at controller level
- CORS Protection: Whitelist-based approach
- Rate Limiting: Prevents abuse
- Environment Isolation: Configuration-based security settings