Skip to content

Deployment

Hosting topology

Component Platform Detail
Reply daemon + outreach cron jobs DigitalOcean droplet (2 vCPU/4GB, nyc3 region) via Coolify Built from deploy/Dockerfile
Warehouse DigitalOcean Managed Postgres See Warehouse Schema
client-api Vercel Public bulk-sync feed, no git auto-deploy — redeploy requires vercel deploy --prod --cwd client-api
internal-api Vercel Internal-only, successor to a retired extension-api/ project
Landing page Vercel landing/

Deprecated

The Chrome extension's backend (extension-api/) was retired. Its Vercel project is not automatically torn down and needs manual decommissioning if not already done.

Needs verification

The droplet's specific size (2 vCPU/4GB) and region (nyc3) should be confirmed against the live DigitalOcean dashboard before being relied on for capacity planning — these can change without a corresponding doc update.

Access

  • SSH to the droplet (key-based; the DigitalOcean cloud firewall must allow the connecting IP).
  • Coolify UI runs on the droplet (same firewall restriction); credentials live in the team password manager.
  • Coolify's own API is reachable from the VPS only (loopback), used by a wrapper script for deploy/log operations.

Deploy procedure

Note

There is no auto-deploy webhook — every deploy is manually triggered.

  1. Merge to main.
  2. Trigger a deploy via the Coolify UI (app → Deploy) or the wrapper script over SSH.
  3. Coolify pulls main, builds the Docker image (~4–5 minutes, most of it the Playwright/Chromium layer), and swaps the running container.
  4. Verify the boot log shows the expected startup sequence (senders config loaded, cron scheduler started, reply daemon started).

Warning

A failed build can leave the old container running with an identical-looking healthy log. Always confirm via the Coolify UI's Deployments tab that the container's build timestamp actually changed — don't rely on the logs looking fine.

Shadow / safe-staging mode

If the sender-pool secret isn't configured, the container boots in cron-only mode with no reply daemon — a safe default for staging.

To safely test a risky change:

  • Run the already-built image as a throwaway container with send-enabling environment variables scrubbed, or
  • Duplicate the Coolify app with a scrubbed-env staging copy.

Rollback

  • Normal (bad code, infra fine): revert the commit on main and redeploy, or use Coolify's "redeploy previous successful deployment." The data volume and environment are untouched by a rollback.
  • To stop the stack entirely: stop the running container via SSH/docker.

Danger

Never run the stopped stack alongside any secondary/fallback deployment target at the same time — that risks double-sending outreach messages.

The Windows scrape box (separate deploy surface)

A separate Windows machine runs Task Scheduler jobs for the paid/manual pipeline stages (weekly enrichment, unit refresh) — see Scheduled Jobs for the task list. It's registered via a PowerShell registration script and reads its own local .env file (distinct from the Coolify environment — see Environment Variables & Secrets).

Logs & data

  • Container logs via docker logs.
  • Per-job logs persist across deploys under a path on the Docker data volume.
  • The communications table in Postgres (see Warehouse Schema) is the ledger of record for all outreach; the data volume additionally holds working files (page-fetch cache, dead-domain list, form-probe records) that survive redeploys.

See also