Current production-style topology
The active docker-compose.coolify.yml defines these runtime services:
app— Laravel 12 web/API application.migrate— one-shot migration container that must complete before the app starts.horizon— Laravel Redis queue workers.scheduler—php artisan schedule:work.postgres— PostgreSQL 16 + PostGIS 3.4.redis— cache, sessions, queues and coordination.go-sync— mobile sync front door and native high-volume writers.go-bulk-import— heavy import worker.go-dashboard— Campaign analytics/outbox projection worker.go-xlsform— Flow XLSForm row-streaming accelerator.go-report— streaming Campaign/Workforce/Flow export worker.livekit— self-hosted media server for meeting features.turn— coturn relay for peer-to-peer calls where enabled.
Network boundary
The reverse proxy terminates HTTPS for the web application. PostgreSQL, Redis and Go worker HTTP ports stay private on the container network. Real-time media is the exception: LiveKit/TURN require explicit TCP/UDP firewall rules for media traffic.
State boundary
Containers are replaceable. Keep PostgreSQL data, Redis persistence where required, and application artefacts on named volumes or managed services. The current local-disk worker model uses the same app_storage volume for Laravel, Go report and Go bulk import so each process sees the same disk-relative paths.
Scaling choices
For a small single-host deployment, use the conservative Coolify resource limits. For larger campaign workloads, apply the full-scale overlay or split PostgreSQL, Redis, object storage and worker services into independently managed infrastructure.