Skip to main content

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

  1. Neon account
  2. A Neon project with logical replication enabled

Step 1: Create Neon Project

  1. Go to Neon Console
  2. Create a new project
  3. 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.

Step 3: Configure Agent Diff

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

cd ops
make up-external
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:
  1. Alembic migrations run
  2. Seed scripts create templates
  3. 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:
  1. Use short idle timeouts
  2. Clean up environments promptly
  3. 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:
  1. Use dedicated compute: Disable scale-to-zero in Neon for consistent latency
  2. Increase pool targets: Minimize pool misses
  3. 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