Run Workers on CircleCI Cloud
Platform: CircleCI Cloud (managed SaaS) | Database: PostgreSQL | Difficulty: Easy-Medium
This guide is specifically for CircleCI Cloud (the managed service at circleci.com), NOT self-hosted runners. If you want to use self-hosted runners, see CircleCI Self-Hosted Runner Guide.
How CircleCI Cloud Works for Workers
Section titled “How CircleCI Cloud Works for Workers”CircleCI Cloud runs jobs in ephemeral Docker containers that are destroyed after the job ends. This is fundamentally different from a traditional background worker:
| Feature | Traditional Worker | CircleCI Cloud |
|---|---|---|
| Lifetime | Runs forever | Max 5 hours per job |
| Storage | Persistent disk | Ephemeral (lost after job) |
| Database | Local or network | Must be external (network-accessible) |
| Redis | Local or network | Must be external |
| Cost | Server rental | Compute minutes |
Bottom line: CircleCI Cloud workers run in short bursts and connect to external services. This is actually perfect for OpenCodeHub’s architecture because the worker code is stateless — all state lives in PostgreSQL + Redis.
Prerequisites
Section titled “Prerequisites”Before you start, you need:
- CircleCI Account (free tier works)
- External PostgreSQL database (required — local DB won’t persist)
- External Redis (required — local Redis won’t persist)
- Git repository pushed to GitHub/GitLab/Bitbucket (CircleCI connects to it)
Recommended PostgreSQL Providers
Section titled “Recommended PostgreSQL Providers”| Provider | Free Tier | Best For |
|---|---|---|
| Supabase | 500MB, 2GB egress | Full-featured, good dashboard |
| Neon | 500MB, 3 databases | Serverless, scales to zero |
| Railway | $5 credit | Simple, pay-as-you-go |
| Render | 1GB | Easy setup |
| AWS RDS | None | Enterprise |
Recommended Redis Providers
Section titled “Recommended Redis Providers”| Provider | Free Tier | Best For |
|---|---|---|
| Upstash | 10,000 commands/day | Serverless, HTTP API |
| Redis Cloud | 30MB | Managed Redis |
| Railway | $5 credit | Easy setup |
| KeyDB | Self-host | Performance |
Step 1: Set Up External PostgreSQL
Section titled “Step 1: Set Up External PostgreSQL”Using Supabase (Recommended)
Section titled “Using Supabase (Recommended)”- Go to supabase.com and create a project
- In Project Settings → Database, copy the connection string:
postgresql://postgres:[password]@db.xxxxxxxxxx.supabase.co:5432/postgres
- Create the
opencodehubdatabase:CREATE DATABASE opencodehub;
Using Neon
Section titled “Using Neon”- Go to neon.tech and create a project
- Copy the connection string from the dashboard
- Create the database:
CREATE DATABASE opencodehub;
Step 2: Set Up External Redis
Section titled “Step 2: Set Up External Redis”Using Upstash (Recommended for Serverless)
Section titled “Using Upstash (Recommended for Serverless)”- Go to upstash.com and create a Redis database
- Copy the Redis URL:
rediss://default:[password]@xxxx.upstash.io:6379
- Enable TLS (Upstash requires it)
Step 3: Configure CircleCI Project
Section titled “Step 3: Configure CircleCI Project”3.1 Connect Repository
Section titled “3.1 Connect Repository”- Go to app.circleci.com
- Click Projects → Set Up Project
- Select your OpenCodeHub repository
- CircleCI will detect
.circleci/config.yml
3.2 Create a Context (Recommended)
Section titled “3.2 Create a Context (Recommended)”Contexts let you share environment variables across jobs securely.
- Go to Organization Settings → Contexts
- Click Create Context
- Name it:
opencodehub-production - Add these environment variables:
| Variable | Value | Description |
|---|---|---|
DATABASE_URL | postgresql://... | Your PostgreSQL connection string |
DATABASE_DRIVER | postgres | Explicitly set driver |
REDIS_URL | redis://... or rediss://... | Your Redis URL |
JWT_SECRET | openssl rand -hex 32 | Generate this |
SESSION_SECRET | openssl rand -hex 32 | Generate this |
INTERNAL_HOOK_SECRET | openssl rand -hex 32 | Generate this |
CRON_SECRET | openssl rand -hex 32 | Generate this |
RUNNER_SECRET | openssl rand -hex 32 | Generate this |
WORKFLOW_SECRET_ENCRYPTION_KEY | openssl rand -hex 32 | Generate this |
SITE_URL | https://git.yourdomain.com | Your OpenCodeHub URL |
SKIP_REDIS_CHECK | 1 | Skip Redis check during build |
Security: Never commit these values to git. Always use CircleCI contexts or project environment variables.
3.3 Alternative: Project-Level Environment Variables
Section titled “3.3 Alternative: Project-Level Environment Variables”If you don’t want to use contexts:
- Go to Project Settings → Environment Variables
- Add each variable individually
Step 4: Initialize Database Schema
Section titled “Step 4: Initialize Database Schema”Before the worker can run, the database schema must exist. Run this once:
# On your local machine with DATABASE_URL setexport DATABASE_URL="postgresql://postgres:[password]@db.xxxxxxxxxx.supabase.co:5432/opencodehub"
# Install dependenciesbun install
# Push schema to databasebun run db:push
# Or generate and run migrationsbun run db:generatebun run db:migrate
# Create admin userbun run scripts/seed-admin.tsImportant: Do this from your local machine or a one-time job. The CircleCI worker job won’t create the schema automatically.
Step 5: Understanding the CircleCI Cloud Config
Section titled “Step 5: Understanding the CircleCI Cloud Config”The .circleci/config.yml in your repo has multiple approaches:
Option A: Scheduled Tasks (Recommended for Free Plan)
Section titled “Option A: Scheduled Tasks (Recommended for Free Plan)”Jobs run on a cron schedule. Each job starts, does its work, and exits.
workflows: scheduled-merge-queue: triggers: - schedule: cron: "*/15 * * * *" # Every 15 minutes jobs: - merge-queue: context: opencodehub-productionWhat happens:
- CircleCI starts a Docker container every 15 minutes
- Installs Bun and dependencies
- Runs
bun run scripts/worker.tsfor 30 minutes - Processes all pending merge queue items
- Container is destroyed
Pros: Works on free plan, reliable, no timeouts Cons: 15-minute delay between processing (jobs only run on schedule)
Option B: Continuous Worker (Performance Plan)
Section titled “Option B: Continuous Worker (Performance Plan)”One long-running job that stays active until timeout.
workflows: worker-continuous: jobs: - worker: context: opencodehub-productionWhat happens:
- CircleCI starts a container
- Worker runs continuously, processing items every 5 seconds
- Job runs until the 5-hour timeout
- CircleCI restarts the job automatically
Pros: Near real-time processing Cons: Requires Performance plan (5h jobs), uses more compute minutes
Option C: API-Triggered (Event-Driven)
Section titled “Option C: API-Triggered (Event-Driven)”OpenCodeHub calls CircleCI API when events happen.
In your OpenCodeHub webhook handler:
// When merge queue needs processingasync function triggerCircleCIWorker(eventType: string, repoId: string) { const response = await fetch( `https://circleci.com/api/v2/project/gh/${org}/${repo}/pipeline`, { method: "POST", headers: { "Circle-Token": process.env.CIRCLECI_API_TOKEN!, "Content-Type": "application/json", }, body: JSON.stringify({ branch: "main", parameters: { event_type: eventType, repo_id: repoId, }, }), } ); return response.json();}Pros: Only runs when needed, most efficient Cons: Requires code changes in OpenCodeHub, more complex setup
Step 6: Choose Your Plan
Section titled “Step 6: Choose Your Plan”Free Plan (Recommended to Start)
Section titled “Free Plan (Recommended to Start)”workflows: scheduled-merge-queue: triggers: - schedule: cron: "*/15 * * * *" # Every 15 min jobs: - merge-queue: context: opencodehub-productionMonthly usage: ~2,880 minutes (48 runs/day × 30 days × 2 min avg) Free tier: 6,000 minutes/month ✅
Performance Plan (For Production)
Section titled “Performance Plan (For Production)”workflows: worker-continuous: jobs: - worker: context: opencodehub-productionMonthly usage: ~7,200 minutes (5h × 24/day × 30 days) Performance plan: Included in price
Step 7: Database Connection from CircleCI Cloud
Section titled “Step 7: Database Connection from CircleCI Cloud”Since CircleCI Cloud containers are ephemeral, the database must be network-accessible.
Connection String Format
Section titled “Connection String Format”# SupabaseDATABASE_URL=postgresql://postgres:[password]@db.xxxxxxxxxx.supabase.co:5432/opencodehub
# Neon (with SSL)DATABASE_URL=postgresql://[user]:[password]@ep-xxxxx.us-east-1.aws.neon.tech:5432/opencodehub?sslmode=require
# RailwayDATABASE_URL=postgresql://postgres:[password]@containers-xxxxx.railway.app:5432/railway
# AWS RDS (with SSL)DATABASE_URL=postgresql://opencodehub:[password]@my-db.xxxxx.us-east-1.rds.amazonaws.com:5432/opencodehub?sslmode=requireSSL/TLS Configuration
Section titled “SSL/TLS Configuration”Most managed PostgreSQL require SSL. The worker handles this automatically when sslmode=require is in the URL.
For Supabase, add this to your environment variables:
DATABASE_SSL=trueDATABASE_SSL_REJECT_UNAUTHORIZED=false # Supabase uses self-signed certsStep 8: Redis Connection from CircleCI Cloud
Section titled “Step 8: Redis Connection from CircleCI Cloud”Upstash Redis URL
Section titled “Upstash Redis URL”REDIS_URL=rediss://default:[password]@xxxx.upstash.io:6379Note:
rediss://(with double s) = TLS enabled. Upstash requires TLS.
Redis Cloud
Section titled “Redis Cloud”REDIS_URL=redis://default:[password]@redis-xxxxx.redis-cloud.com:12345Testing Connection
Section titled “Testing Connection”You can test the connection from CircleCI by running the health-check job:
# Trigger manually from CircleCI dashboard# or wait for the scheduled health checkStep 9: Monitoring
Section titled “Step 9: Monitoring”View Job Logs
Section titled “View Job Logs”- Go to app.circleci.com
- Select your project
- Click on any job to see real-time logs
Set Up Notifications
Section titled “Set Up Notifications”- Project Settings → Notifications
- Connect Slack, email, or webhooks
- Get alerts when jobs fail
Track Compute Usage
Section titled “Track Compute Usage”- Plan → Usage
- Monitor minutes used per month
- Set up usage alerts
Step 10: Troubleshooting
Section titled “Step 10: Troubleshooting”| Problem | Solution |
|---|---|
| ”Database connection refused” | Your PostgreSQL doesn’t allow external connections. Check provider’s “Connection Pooling” or “Network” settings. For Supabase, go to Database → Connection Pooling. |
| ”Redis connection timeout” | Redis provider blocks unknown IPs. Add CircleCI’s IP ranges to allowlist. Or use Upstash which doesn’t require IP allowlisting. |
| Job killed after 1 hour | Free plan default timeout is 1 hour. Add no_output_timeout: 5h or upgrade to Performance plan. |
| ”Out of memory” | Use resource_class: large instead of medium. Or optimize the worker memory usage. |
| ”bun install fails” | Network issues. The config has retry logic, but you can also try npm install as fallback. |
| ”Schema doesn’t exist” | Run bun run db:push from your local machine first to create tables. |
| Worker starts but does nothing | Check that DATABASE_URL points to the right database and that the mergeQueueItems table has rows with status = 'queued'. |
| ”SSL certificate verify failed” | Add DATABASE_SSL_REJECT_UNAUTHORIZED=false for providers with self-signed certs (Supabase). |
Architecture Diagram
Section titled “Architecture Diagram”┌─────────────────────────────────────────────────────────────┐│ CircleCI Cloud ││ ┌─────────────────┐ ┌─────────────────┐ ││ │ Docker Container │ │ Docker Container │ ... ││ │ (every 15 min) │ │ (every 15 min) │ ││ │ │ │ │ ││ │ bun run worker.ts│ │ bun run worker.ts│ ││ │ │ │ │ ││ │ ┌─────────────┐ │ │ ┌─────────────┐ │ ││ │ │ Node.js/Bun │ │ │ │ Node.js/Bun │ │ ││ │ │ Worker Loop │ │ │ │ Worker Loop │ │ ││ │ └─────────────┘ │ │ └─────────────┘ │ ││ └────────┬─────────┘ └────────┬─────────┘ │└───────────┼─────────────────────┼────────────────────────────┘ │ │ │ TCP/IP (Internet) │ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ PostgreSQL │ │ Redis │ │ (Supabase) │ │ (Upstash) │ │ │ │ │ │ merge_queue │ │ sessions │ │ repositories │ │ rate limits │ │ pull_requests │ │ job queues │ └──────────────┘ └──────────────┘Quick Start Checklist
Section titled “Quick Start Checklist”- Create PostgreSQL database (Supabase/Neon/Railway)
- Create Redis database (Upstash/Redis Cloud)
- Run
bun run db:pushfrom local machine - Push OpenCodeHub code to GitHub
- Connect repo to CircleCI
- Create Context
opencodehub-productionwith all env vars - Verify
.circleci/config.ymlis in repo root - Trigger first job manually from CircleCI dashboard
- Check job logs for ”✅ Worker started”
- Create a test PR and verify merge queue processes it
Next Steps
Section titled “Next Steps”- CircleCI Integration Guide — For CI/CD pipelines (separate from worker)
- Deployment Guide — Full production setup
- Self-Hosted Runner Guide — If you prefer self-hosted over Cloud
- Merge Queue — How merge queue works