Overview
Neon is a serverless PostgreSQL that scales to zero. It’s great for:
- Development environments
- Cost optimization (pay only when active)
- Auto-scaling
Prerequisites
- Neon account
- A Neon project with logical replication enabled
Step 1: Create Neon Project
- Go to Neon Console
- Create a new project
- Important: Enable logical replication:
- Go to Project Settings → Logical Replication
- Enable it
Step 2: Get Connection String
From your Neon dashboard, copy the pooled connection string:
postgresql://user:pass@ep-xxx-xxx.us-east-1.aws.neon.tech/dbname?sslmode=require
Use the pooled connection string (contains -pooler in the hostname) for better performance with many connections.
Create .env file in ops/:
DATABASE_URL=postgresql://user:pass@ep-xxx-xxx-pooler.us-east-1.aws.neon.tech/dbname?sslmode=require
LOGICAL_REPLICATION_ENABLED=true
SEED=true # Only first time
Step 4: Start Agent Diff
Or directly:
docker-compose --profile external up -d backend-external
Neon-Specific Configuration
Scale-to-Zero Support
Agent Diff’s on-demand services work well with Neon’s scale-to-zero:
# Short idle timeouts (Neon scales to zero after ~5 min idle)
MAINTENANCE_IDLE_TIMEOUT=60
REPLICATION_IDLE_TIMEOUT=60
Connection Pooling
Neon uses PgBouncer for connection pooling. Agent Diff auto-detects this and disables its own pooling:
# In main.py - auto-detects -pooler in URL
if "-pooler" in db_url:
engine = create_engine(db_url, poolclass=NullPool)
Replication Slot Limits
Neon limits replication slots to 10 per project. Agent Diff uses a single global slot, so this is not a problem for normal usage.
First Time Setup
On first run with SEED=true:
- Alembic migrations run
- Seed scripts create templates
- Pool schemas are pre-created
This may take 1-2 minutes.
Subsequent Runs
After initial setup:
SEED=false docker-compose --profile external up -d backend-external
Monitoring
Check Connection
curl http://localhost:8000/api/platform/health
View Logs
docker-compose logs -f backend-external
Check Replication
In Neon SQL Editor:
SELECT slot_name, active
FROM pg_replication_slots;
You should see diffslot_global.
Cost Optimization
Compute Hours
Neon bills for compute hours. To minimize costs:
- Use short idle timeouts
- Clean up environments promptly
- Reduce pool targets if not needed
# Minimal pool (faster startup but slower test starts)
ENVIRONMENT_POOL_TARGETS="slack_default:5,linear_expanded:5"
Storage
Neon bills for storage. Pooled schemas use storage. Balance between:
- More pools = faster tests, more storage
- Fewer pools = slower tests, less storage
Troubleshooting
Connection Timeouts
Neon connections can drop on idle. Agent Diff handles this with:
- Connection retries
- NullPool (no stale connections)
If you see SSL SYSCALL error: EOF detected, it’s normal - retries should handle it.
Replication Not Working
Check that logical replication is enabled:
SHOW wal_level; -- Should be 'logical'
If not, enable it in Neon Console → Project Settings → Logical Replication.
Slow First Request
After Neon scales to zero, the first request takes 1-3 seconds to “wake up” the database. Subsequent requests are fast.
Production Considerations
For production use:
- Use dedicated compute: Disable scale-to-zero in Neon for consistent latency
- Increase pool targets: Minimize pool misses
- Monitor replication lag: Ensure diffs are captured in time
# Production settings
ENVIRONMENT_POOL_TARGETS="slack_default:100,linear_expanded:100"
POOL_REFILL_CONCURRENCY=10
MAINTENANCE_IDLE_TIMEOUT=300
Next Steps