Deployment
Production deployment guide with Docker Compose, database migrations, and webhook registration.
This document describes how to deploy the Meta Business MCP system in a production environment.
Prerequisites
- Docker & Docker Compose (version 20.10+ / Compose V2)
- PostgreSQL 16 (or AWS RDS PostgreSQL)
- Redis 7 (or AWS ElastiCache Redis)
- NATS Server (with JetStream enabled)
- WhatsApp Business API Account Credentials (from Meta Developer Console)
Infrastructure Dependencies
| Dependency | Minimum Version | Notes |
|---|---|---|
| PostgreSQL | 16 | AWS RDS compatible |
| Redis | 7 | AWS ElastiCache compatible |
| NATS Server | Latest stable | Must enable JetStream (--jetstream) |
| Go | 1.21+ | Build only |
| Docker | 20.10+ | Compose V2 required |
1. Environment Configuration
Create a production .env configuration file in your project root:
# Server settings
SERVER_HTTP_PORT=8080
SERVER_MCP_NAME=meta-business-mcp
SERVER_MCP_VERSION=1.0.0
TIER=oss
# Database connections
DB_HOST=postgres.prod.internal
DB_PORT=5432
DB_USER=mcp_user
DB_PASSWORD=production_secure_postgres_pass
DB_NAME=meta_mcp
DB_SSLMODE=require
# Cache connection
REDIS_ADDR=redis.prod.internal:6379
REDIS_PASSWORD=production_redis_auth_pass
REDIS_DB=0
# Message broker connection
NATS_URL=nats://nats.prod.internal:4222
# Meta Cloud API credentials
META_API_URL=https://graph.facebook.com
META_ACCESS_TOKEN=EAAG...production_long_lived_system_user_token...
META_PHONE_NUMBER_ID=106555123456789
META_WABA_ID=204555123456789
META_WEBHOOK_VERIFY_TOKEN=production_webhook_verification_passphrase
# Policies file path
POLICIES_PATH=/app/policies.yaml
SCHEDULER_POLL_INTERVAL=30s2. Docker Compose Deployment
A standard production docker-compose.prod.yaml:
services:
postgres:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: mcp_user
POSTGRES_PASSWORD: production_secure_postgres_pass
POSTGRES_DB: meta_mcp
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U mcp_user -d meta_mcp"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
restart: always
command: redis-server --requirepass production_redis_auth_pass
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "production_redis_auth_pass", "ping"]
interval: 10s
timeout: 5s
retries: 5
nats:
image: nats:alpine
restart: always
command: "--jetstream -m 8222"
ports:
- "4222:4222"
volumes:
- natsdata:/data
healthcheck:
test: ["CMD", "nc", "-z", "localhost", "4222"]
interval: 10s
timeout: 5s
retries: 5
app:
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- "8080:8080"
env_file:
- .env
volumes:
- ./policies.yaml:/app/policies.yaml
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nats:
condition: service_healthy
volumes:
pgdata:
redisdata:
natsdata:Launch Services
docker compose -f docker-compose.prod.yaml up -d --build3. Build the Binary (Non-Docker)
go build -o mcp-server ./cmd/server/main.go4. Database Migrations & Seeding
No external migration runner is required. On startup, the application automatically:
- Creates all database tables (
customers,conversations,messages,templates,policies,campaigns,message_frequencies,error_knowledge_base,audit_logs,conversation_pricing). - Seeds standard Meta error codes into
error_knowledge_base. - Seeds business policies from
policies.yamlusing idempotentON CONFLICT DO UPDATE. - Seeds conversation pricing data for ID, US, IN, BR, GB, and DEFAULT fallback.
All schema changes use IF NOT EXISTS / ADD COLUMN IF NOT EXISTS. Existing deployments upgrade by restarting the application.
5. Webhook Registration
Register the public URL in the Meta App Developer Portal:
- Verification:
GET /webhook— responds withhub.challenge. - Events:
POST /webhook— receives inbound messages, status updates, and template events. - Signature validation:
X-Hub-Signature-256header is verified on all POST events.
6. Health Checks & Verification
# Verify health check
curl http://localhost:8080/health
# Response: OK
# Verify Prometheus metrics
curl http://localhost:8080/metrics
# Response: Prometheus metric scrape outputObservability Endpoints
| Endpoint | Method | Response |
|---|---|---|
/health | GET | 200 OK — body: "OK" |
/metrics | GET | 200 OK — Prometheus scrape payload |
/webhook | GET | 200 OK — webhook challenge echo |
/webhook | POST | 200 OK — body: "EVENT_RECEIVED" |
Logging
Structured logs are written to stdout/stderr. Collect via Docker:
docker compose logs -f appNATS Monitoring
NATS monitoring HTTP interface is available at :8222. Stream and consumer stats: http://localhost:8222/jsz.