The AI Present Finder production deployment is optimized for cost-effectiveness and simplicity while maintaining the microservices architecture internally.
┌─────────────────────────────────────────────────────────────┐
│ Coolify │
│ ┌────────────────┐ ┌──────────────────────┐ │
│ │ Frontend │ │ App Container │ │
│ │ (Nginx) │◄─────────────┤ (All Services) │ │
│ │ Port 80 │ │ Port 3000 │ │
│ └────────────────┘ └──────────────────────┘ │
│ │ │
│ │ │
│ ┌────────────────┐ ┌──────────────────────┐ │
│ │ PostgreSQL │◄─────────────┤ RabbitMQ │ │
│ │ (5 DBs) │ │ Port 5672 │ │
│ └────────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
A single Docker container running multiple Node.js processes managed by PM2:
┌────────────────────────────────────────────────────┐
│ App Container (Node 22 Alpine) │
├────────────────────────────────────────────────────┤
│ PM2 Process Manager │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ restapi-macroservice Port 3000 │ │
│ │ ├─ HTTP/REST API │ │
│ │ └─ SSE (Server-Sent Events) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ stalking-microservice Port 3010 │ │
│ │ └─ User data analysis via BrightData │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ chat-microservice Port 3020 │ │
│ │ └─ Interview flow (OpenAI) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ gift-microservice Port 3030 │ │
│ │ └─ Gift generation logic │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ gift-ideas-microservice Port 3040 │ │
│ │ └─ AI-powered gift suggestions │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ reranking-microservice Port 3050 │ │
│ │ └─ Gift ranking and filtering │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ fetch-microservice-olx Port 8011 │ │
│ │ fetch-microservice-allegro Port 8012 │ │
│ │ fetch-microservice-ebay Port 8013 │ │
│ │ fetch-microservice-amazon Port 8014 │ │
│ │ └─ Product fetching from various platforms │ │
│ └──────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │────────▶│ Frontend │────────▶│ REST │
│ │◀────────│ (Nginx) │◀────────│ API │
└──────────┘ └──────────┘ └──────────┘
│
▼
┌────────────────────────────────┐
│ RabbitMQ Queues │
│ ┌──────────────────────────┐ │
│ │ StalkingAnalyzeRequested │ │
│ │ ChatStartInterview │ │
│ │ ChatUserAnswered │ │
│ │ GiftGenerateRequested │ │
│ │ ... │ │
│ └──────────────────────────┘ │
└────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Stalking │ │ Chat │ │ Gift │
│ Service │ │ Service │ │ Service │
└────────────┘ └────────────┘ └────────────┘
│ │ │
└───────────────┼───────────────┘
▼
┌────────────────────────┐
│ PostgreSQL │
│ ┌──────────────────┐ │
│ │ stalking_service │ │
│ │ chat_service │ │
│ │ gift_ideas_svc │ │
│ │ reranking_svc │ │
│ │ fetch_service │ │
│ └──────────────────┘ │
└────────────────────────┘
User → Frontend → REST API → SSE Connection
│
├─ Publish: StalkingAnalyzeRequestedEvent
├─ Publish: ChatStartInterviewEvent
└─ Stream updates via SSE
RabbitMQ Queue → Microservice Handler → Database Write
└─ Emit new event → RabbitMQ
Microservice → Publish Event → RabbitMQ
│
▼
REST API subscribes
│
▼
Push via SSE → Frontend
Single PostgreSQL instance with isolated databases:
PostgreSQL Instance (postgres:16)
├── reranking_service
│ └── User: reranking_user
├── fetch_service
│ └── User: fetch_user
├── stalking_service
│ └── User: stalking_user
├── chat_service
│ └── User: chat_user
└── gift_ideas_service
└── User: gift_ideas_user
RabbitMQ queues (non-durable):
RabbitMQ
├── StalkingAnalyzeRequestedEvent
├── StalkingCompletedEvent
├── ChatStartInterviewEvent
├── ChatQuestionAskedEvent
├── ChatUserAnsweredEvent
├── ChatInterviewCompletedEvent
├── ChatInappropriateRequestEvent
├── GiftGenerateRequestedEvent
├── GiftReadyEvent
└── ... (other events)
Queue names match the event class name (EventClass.name).
All services communicate via Docker's internal network:
- Service-to-Service:
http://<service-name>:<port> - Database:
postgresql://<user>:<pass>@postgres:5432/<db> - RabbitMQ:
amqp://admin:admin@rabbitmq:5672
Coolify provides the reverse proxy:
Internet
│
▼
┌─────────────────┐
│ Coolify Proxy │
│ (Traefik) │
└─────────────────┘
│ │
│ └──────────────┐
▼ ▼
┌──────────┐ ┌──────────────┐
│ Frontend │ │ App (REST) │
│ Port 80 │ │ Port 3000 │
└──────────┘ └──────────────┘
Pros:
- Low resource usage
- Fast inter-service communication (localhost)
- Simple deployment
- Cost-effective
Cons:
- Single point of failure
- Vertical scaling only
- All services restart together
Move RabbitMQ and PostgreSQL to external services:
┌────────┐ ┌────────┐ ┌────────┐
│ App 1 │ │ App 2 │ │ App 3 │
└───┬────┘ └───┬────┘ └───┬────┘
└───────────┼───────────┘
│
┌───────┴────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ PostgreSQL │ │ RabbitMQ │
│ (Managed) │ │ (Managed) │
└──────────────┘ └──────────────┘
Split into multiple containers:
┌──────────┐
│ REST │
│ API │
└──────────┘
│
┌────┴─────┬─────────┬──────────┐
▼ ▼ ▼ ▼
┌────┐ ┌────┐ ┌──────┐ ┌──────┐
│Chat│ │Gift│ │Stalk │ │Fetch │
└────┘ └────┘ └──────┘ └──────┘
- CPU: 2 cores
- RAM: 4 GB
- Storage: 10 GB
- CPU: 4 cores
- RAM: 8 GB
- Storage: 20 GB SSD
- CPU: 8 cores
- RAM: 16 GB
- Storage: 50 GB SSD
- No exposed ports (Coolify handles ingress)
- Internal Docker network for service communication
- Database access restricted to app container
- Environment variable-based secrets
- No hardcoded credentials
- HTTPS enforced by Coolify
- Security headers in Nginx
- Separate users per service
- Isolated databases
- Strong passwords required
- App Container: HTTP GET to
http://localhost:3000/health - PostgreSQL:
pg_isready -U postgres - RabbitMQ:
rabbitmq-diagnostics -q ping - Frontend: HTTP GET to
http://localhost/health
- CPU Usage: All services in app container
- Memory Usage: App container, PostgreSQL, RabbitMQ
- Disk I/O: PostgreSQL volume
- Network: RabbitMQ message throughput
- Response Times: REST API endpoints
- Error Rates: Application logs
- Queue Depths: RabbitMQ queues
# Automated daily backups
pg_dump -U postgres <database_name> > backup-$(date +%Y%m%d).sqlpostgres_data→ Daily backupsrabbitmq_data→ Weekly backups (optional)
- Target: < 30 minutes
- Target: < 24 hours (daily backups)
- Provision new Coolify instance
- Restore database from backup
- Deploy docker-compose.prod.yml
- Restore environment variables
- Assign domains and verify
- PM2 cluster mode for CPU-bound tasks
- Connection pooling for PostgreSQL
- RabbitMQ prefetch limits
- Indexes on frequently queried fields
- Connection pooling
- Query optimization
- Static assets cached by Nginx (1 year)
- Database query caching (application level)
- CDN for static assets (optional)
- Single container reduces compute costs
- Single PostgreSQL instance instead of 5
- Efficient resource usage with PM2
- No managed services required
- Small Instance (2 CPU, 4GB RAM): $10-20
- Medium Instance (4 CPU, 8GB RAM): $40-60
- Large Instance (8 CPU, 16GB RAM): $80-120
Plus:
- Domain + SSL: $0 (Let's Encrypt)
- Coolify: $0 (self-hosted)
- External APIs: Variable (OpenAI, BrightData)