Skip to Content
InfraAutomation options

Automation tooling options for Oter

Reference for picking a workflow/automation tool when an actual need appears. Optimised for lowest cost first — Oter is solo-developed and most automations are low-frequency. Re-read this before adding a new hosted tool.

TL;DR

NeedCheapest fitMonthly cost
Cron job in a repo (lint, sync, mirror, scheduled tests)GitHub Actions schedule:$0 (free tier 2000 min/mo private)
Periodic backend job (DB query, email digest, scheduled finance check)Cloud Scheduler → Cloud Run job$0.10 – $2
Webhook listener (Stripe, etc.)Cloud Run service (min=0)cents/month idle
Multi-step recurring workflow with visual UIn8n self-hosted on Cloud Run (min=0)$0–5 when idle, scales with use
Long-running stateful workflows, retries, fan-outTemporal Cloud free tier or Inngest free tier$0 up to a low ceiling
Many GUI-built recipes, low volumeMake.com / Zapier / n8n.cloud free tier$0 (1k ops/mo)
Heavyweight Windmill-style platformStripped Windmill on Cloud Run$50+/mo always-on

Default recommendation: start with GitHub Actions cron for anything that can live in this repo, and Cloud Scheduler + Cloud Run jobs for anything that needs GCP IAM or talks to oter-db directly. Don’t introduce a hosted workflow engine until you have at least 5–10 multi-step automations that can’t be expressed as a script.

Why Windmill was removed

Earlier the repo carried a deploy workflow + runbook for Windmill on Cloud Run worker pools (--cpu=2 --memory=2Gi --instances=1, two pools). The always-on bill was ~$210/month before running a single workflow, because Cloud Run worker pools cannot scale to zero. With Oter’s actual automation needs (none yet), this was a fixed cost with no payoff.

The Windmill files were deleted in this commit; they remain in git history if you want to revert.

Detailed comparison

1. GitHub Actions (schedule: cron, workflow_dispatch)

Already in use: .github/workflows/server-maintenance.yml runs weekly on Sunday 05:00 UTC.

  • Cost: Free for public repos. Private repos: 2000 minutes/month free, then ~$0.008/min on Linux.
  • Strengths: Code lives next to app code; version controlled; full secret + OIDC access; can ssh, run gcloud, hit any API.
  • Weaknesses: Cold-start latency (~20s); cron precision is “approximately on time”; no native UI for non-engineers; max 6 hours/job.
  • Use when: Cron job, repo-scoped, no need for “always on” connection.
on: schedule: - cron: "0 5 * * *" # daily 05:00 UTC workflow_dispatch:

2. Cloud Scheduler → Cloud Run job

Cloud Run jobs (different from services) are containers that run to completion. Combined with Cloud Scheduler they become managed cron with full GCP IAM and Cloud SQL access.

  • Cost:
    • Cloud Scheduler: 3 jobs free/month, then $0.10/job/month.
    • Cloud Run job execution: per-second CPU + RAM only while running. A daily 30-second job on 1 vCPU + 512 MiB ≈ $0.01/mo.
  • Strengths: Same image build path as the API; reuses Artifact Registry, WIF, Secret Manager; native Cloud SQL Auth Proxy; scale-to-zero (no idle cost).
  • Weaknesses: No UI; one container per job; orchestration of multi-step flows is on you.
  • Use when: Recurring backend task that needs GCP credentials or Cloud SQL.

Example skeleton (no current jobs deployed):

# Build image (or reuse the oter server image with a different entrypoint). gcloud run jobs create oter-finance-digest \ --image=us-east1-docker.pkg.dev/oter-490318/oter/finance-digest:latest \ --region=us-east1 \ --service-account=oter-server-runtime@oter-490318.iam.gserviceaccount.com \ --set-cloudsql-instances=oter-490318:us-east1:oter-db \ --set-secrets=DB_PASSWORD=db-password:latest \ --max-retries=1 gcloud scheduler jobs create http oter-finance-digest-daily \ --schedule="0 7 * * *" \ --time-zone="America/Bogota" \ --uri="https://us-east1-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/oter-490318/jobs/oter-finance-digest:run" \ --http-method=POST \ --oauth-service-account-email=oter-server-runtime@oter-490318.iam.gserviceaccount.com

3. Cloud Run service (min=0) for webhooks

A normal Cloud Run service with --min-instances=0 and --allow-unauthenticated (or auth) is the right shape for receiving webhooks (Stripe, GitHub, custom integrations).

  • Cost: Request-based pricing with generous free tier (180k vCPU-sec, 360k GiB-sec/mo). Effectively $0 for sub-thousand requests/day.
  • Strengths: Same WIF, AR, Cloud SQL pattern; scale-to-zero; HTTPS managed.
  • Weaknesses: Cold starts (1–3 s). For latency-sensitive webhooks set --min-instances=1 ($10–15/mo always-on).
  • Use when: Incoming HTTP event needs immediate handling and state.

4. n8n (self-hosted on Cloud Run)

Open-source workflow tool with visual node editor. Single container, Postgres-backed.

  • Cost: Cloud Run service min=0 + tiny DB in oter-db (separate database, no extra instance). Idle ≈ $0–5/mo; modest use ≈ $10–20/mo.
  • Strengths: UI for building flows; ~500 integrations; community nodes; self-hostable so no per-execution fee.
  • Weaknesses: Container needs persistent disk or external DB for state; cold starts hurt schedule precision; you maintain upgrades. Not as polished as Windmill for code-first.
  • Use when: Many low-volume integrations (Slack, Notion, Gmail, etc.) where the UI saves significant time vs writing scripts.

n8n.cloud’s free tier (~5k executions, 2 active workflows) is also viable if you don’t want to self-host.

5. Temporal Cloud / Inngest (durable workflow services)

  • Cost: Temporal Cloud free tier: 100k actions/mo. Inngest free tier: 50k steps/mo, 3 concurrent runs.
  • Strengths: Real durable execution, retries, timers, fan-out. Best for “workflow” semantics (sagas, async pipelines, AI agent loops).
  • Weaknesses: Overkill for cron-y stuff; paid tiers expensive ($100+/mo) once you exceed free.
  • Use when: Complex multi-step state machines (e.g. multi-stage onboarding flows, AI agent pipelines, scheduled transaction execution chains).

6. Stripped-down Windmill (if you ever want to revisit)

If a Windmill-style script-hub appeals later, the minimum viable cost is:

  • One worker pool, --cpu=1 --memory=1Gi --instances=1$50/mo
  • Server scales to zero, free when idle
  • Reuse oter-db with a separate windmill database

Only justifiable when you have a substantial library of scripts that benefit from Windmill’s UI/runtime over plain Cloud Run jobs.

Decision tree

Re-adding Windmill later

The deleted files are recoverable from the commit that removed them. Search the git log for Kill Windmill and check out:

  • .github/workflows/publish-windmill-cloud-run.yml
  • docs/infra/GCP_WINDMILL_CLOUD_RUN.md
  • infra/automation/ (local Docker Compose)

Before restoring, downscale the workflow defaults: drop the native worker pool, set --cpu=1 --memory=1Gi, and document the expected monthly floor near the top of the runbook.