System Architecture
The Banca Management Backend follows a clean, layered architecture with clear separation of concerns. This design ensures maintainability, testability, and scalability as your lottery management platform grows.Architectural Overview
The system is built using a three-tier layered architecture:Project Structure
The codebase is organized for clarity and modularity:Layer Responsibilities
Controllers Layer
Controllers Layer
Responsibilities:Controllers are thin and delegate all business logic to services.
- Receive HTTP requests and extract parameters
- Validate request data using Zod schemas
- Call appropriate service methods
- Map service responses to HTTP responses
- Handle errors and return proper status codes
Services Layer
Services Layer
Responsibilities:Services contain the core business logic and ensure data consistency.
- Implement business logic and domain rules
- Validate business constraints
- Orchestrate multiple repository operations
- Manage transactions and retries
- Apply hierarchical rules (commissions, restrictions)
- Generate audit logs
Repositories Layer
Repositories Layer
Responsibilities:Repositories are simple and focus solely on data persistence.
- Execute database queries via Prisma
- Provide simple CRUD operations
- No business logic (pure data access)
- Support transactions passed from services
Middlewares
Middlewares
Responsibilities:
- Authentication (JWT validation)
- Authorization (role-based access control)
- Request validation (Zod schemas)
- Rate limiting
- Logging and request tracking
- Error handling
protect- Validates JWT and attaches user to requestvalidateBody- Validates request body against Zod schemarbacMiddleware- Enforces role-based access rulesattachLogger- Adds request-scoped logger
Database Schema
The database follows a hierarchical structure with clear relationships:Core Hierarchy
Key Entities
Banca
Top-level organization
defaultMinBet,globalMaxPerNumbersalesCutoffMinutescommissionPolicyJson- Soft delete support
Ventana
Sales window/point
- Belongs to a Banca
commissionMarginXcommissionPolicyJson- Configuration JSON (print, theme)
User
System users (VENDEDOR role)
- Belongs to a Ventana (optional)
- Role: ADMIN, VENTANA, VENDEDOR
commissionPolicyJson- JWT refresh tokens
Loteria
Lottery game definition
rulesJson(validation rules)- Draw schedule configuration
- Multiplier settings
- Active/inactive state
Sorteo
Individual lottery draw
- State: SCHEDULED → OPEN → CLOSED → EVALUATED
scheduledAt,winningNumber- Extra multiplier support (REVENTADO)
- Unique constraint on (loteriaId, scheduledAt)
Ticket
Sales record
- Sequential
ticketNumber - Status: ACTIVE, PAID, CANCELLED
- Commission snapshots
- Payment tracking fields
Jugada
Individual bet line
- Type: NUMERO or REVENTADO
finalMultiplierXsnapshot- Commission snapshot
- Payout calculation
ActivityLog
Audit trail
- Action, targetType, targetId
- User and context tracking
- JSON details
Supporting Entities
- LoteriaMultiplier - Configurable multipliers per lottery or draw
- MultiplierOverride (UserMultiplierOverride) - User-specific multipliers
- RestrictionRule - Hierarchical betting limits
- BancaLoteriaSetting - Banca-specific lottery configuration
- AccountStatement - Financial account tracking
- TicketPayment - Payment records for winning tickets
The schema uses UUIDs for all primary keys and includes comprehensive indexing for performance. See
prisma/schema.prisma for the complete definition.Technology Stack
The backend leverages modern, production-ready technologies:Core Technologies
Runtime
Node.js 20.xLTS version with TypeScript strict mode for type safety
Framework
Express.js 4.xBattle-tested HTTP framework with extensive middleware ecosystem
ORM
Prisma 6.xType-safe database access with migrations and introspection
Database
PostgreSQL 14+Reliable relational database with transaction support
Key Dependencies
| Package | Purpose | Version |
|---|---|---|
@prisma/client | Database ORM | 6.18.0 |
express | HTTP server | 4.21.2 |
zod | Schema validation | 4.1.11 |
jsonwebtoken | JWT authentication | 9.0.2 |
bcryptjs | Password hashing | 2.4.3 |
pino | Structured logging | 10.0.0 |
ioredis | Redis client (optional) | 5.8.2 |
express-rate-limit | Rate limiting | 8.1.0 |
helmet | Security headers | 8.1.0 |
cors | CORS middleware | 2.8.5 |
date-fns | Date utilities | 4.1.0 |
Development Tools
- TypeScript 5.9 - Static typing and compilation
- Jest 30.x - Testing framework
- Supertest 7.x - HTTP assertion library
- ESLint + Prettier - Code quality and formatting
- Nodemon - Development auto-reload
- dotenv-cli - Environment management
Request Flow
Here’s how a typical authenticated request flows through the system:Middleware Pipeline
Request passes through:
- CORS - Validates origin
- Helmet - Sets security headers
- Rate Limiter - Checks request rate
- Body Parser - Parses JSON body
- Logger - Attaches request-scoped logger
Route Matching
Express router matches the route and applies route-specific middleware:
- protect - Validates JWT, extracts user, attaches to
req.user - validateBody - Validates request body against Zod schema
- rbacMiddleware - Checks role permissions (if applicable)
Controller Execution
Controller method is called:
- Extracts validated data from request
- Calls service method with user context
- Awaits service response
Service Logic
Service implements business logic:
- Validates business rules
- Starts transaction (if needed)
- Calls repository methods
- Applies hierarchical rules (commissions, restrictions)
- Creates audit logs
- Commits or rolls back transaction
Repository Access
Repository executes database operations:
- Uses Prisma Client for type-safe queries
- Participates in transaction (if provided)
- Returns raw data entities
Caching Strategy
The system supports optional Redis caching for performance optimization:Cached Data
- Sales cutoff rules - TTL: 300s (
CACHE_TTL_CUTOFF) - Restriction rules - TTL: 300s (
CACHE_TTL_RESTRICTIONS) - Lottery rules - Invalidated on update
Cache Configuration
If
CACHE_ENABLED=false, the system operates without caching and queries the database directly for all requests.Concurrency and Transaction Safety
The system is designed to handle high-concurrency scenarios safely:Transaction Retry Wrapper
- Handles PostgreSQL deadlocks automatically
- Configurable max retries (
TX_MAX_RETRIES) - Exponential backoff (
TX_BACKOFF_MIN_MStoTX_BACKOFF_MAX_MS) - Detailed logging of retry attempts
- Prevents overselling in concurrent ticket creation
Atomic Operations
- Ticket number generation - Sequential via database function or atomic counter
- Sorteo deduplication - Unique constraint on
(loteriaId, scheduledAt) - Commission snapshots - Immutable at time of sale
- State transitions - Validated within transactions
Performance Features
Database Pooling
Supabase transaction pooler (port 6543) for web requests with connection limits
Read Replicas
Optional
DATABASE_URL_REPLICA for analytics and dashboard queriesIndexed Queries
Comprehensive indexing on frequently queried fields (ticketNumber, dates, status)
Pagination
Cursor and offset-based pagination for large result sets
Query Optimization
Selective field loading, eager loading of relations, and query profiling
Redis Caching
Optional caching layer for frequently accessed configuration data
Security Features
Authentication
JWT-based with access and refresh tokens. Tokens include userId, role, and ventanaId claims.
Authorization
Role-based access control (RBAC) with hierarchical permissions:
- ADMIN - Full system access
- VENTANA - Access to own ventana and vendedores
- VENDEDOR - Access to own tickets and data
Input Validation
All inputs validated with Zod schemas before processing. Type-safe at compile time.
Scalability Considerations
Horizontal Scaling
- Stateless design - No session state stored in-memory
- JWT tokens - No server-side session storage required
- Database pooling - Connection pools managed by Supabase
- Redis cache - Shared cache layer across instances
Vertical Scaling
- Efficient queries - Indexed and optimized for performance
- Transaction batching - Multiple operations in single transaction
- Lazy loading - Relations loaded only when needed
Monitoring
- Structured logging - JSON logs with context for analysis
- Performance metrics - Query execution time tracking
- Error tracking - Sentry integration for production monitoring
- Database metrics - Prisma query logging and slow query detection
For production deployment best practices, see the deployment guide or contact [email protected].