Cada componente, y dónde se ejecuta

Alojado en la UE en una VM de Hetzner en Alemania, tras Cloudflare. Todo el sistema cabe en una vista — y los únicos subencargados son Cloudflare, Paddle y SMTP2GO.

Clientes

Browser

steadycron.com

Sitio y documentación

Browser

app.steadycron.com

Interfaz del panel

CLI / scripts

api.steadycron.com

REST + manifiestos

Your cron

ping.steadycron.com

Pings de heartbeat

Cloudflare

DNS · TLS · WAF · CDN

Proxy edge, firewall y limitación de tasa delante de todo.

Cloudflare Pages

Astro · static

Este sitio, servido en el edge — nunca toca la VM.

Caddy

reverse proxy

En la VM: TLS automático, enruta app. / api. / ping. a los contenedores.

VM de Hetzner · Alemania · Docker Compose

Dashboard

steadycron-dashboard

Next.js. UI autenticada; llama a la API por la red interna.

API + Ping

steadycron-api · .NET

REST · ingesta de ping · vista previa de cron · variables · actividad · admin.

steadycron-scheduler · Quartz.NET clustered

HTTP executor

Polly · SSRF guard

Hace las llamadas HTTPS programadas — reintentos, timeouts, re-chequeo de redirecciones.

Heartbeat watcher

30s tick

Detecta ejecuciones perdidas o atascadas según el periodo de gracia.

Alert dispatcher

outbox · NOTIFY

Vacía la outbox; moldea, entrega y reintenta las alertas.

Background workers

×4 services

Flush de envíos, detección de anomalías, poda de retención, reconciliación de Paddle.

PostgreSQL 17

app · Quartz · outbox

Una instancia para todo. LISTEN/NOTIFY reemplaza un broker — sin Redis.

Backups

nightly · encrypted

pg_dump cifrado, enviado fuera del sitio; pruebas de restauración trimestrales.

Servicios externos y tus sistemas

Your endpoints

the jobs we call

Tus handlers HTTPS, llamados según el calendario.

Alert channels

Slack · Discord · …

Telegram, webhook, correo — solo saliente.

Paddle

billing · MoR

Merchant of Record — gestiona los impuestos. Sin datos de tarjeta aquí.

SMTP2GO

email

Verificación, restablecimiento de contraseña y alertas por correo.

Observabilidad · OpenTelemetry → Grafana autoalojado Infraestructura como código · Terraform (Cloudflare + Hetzner) Planificación · Quartz.NET en clúster (AdoJobStore)

Ejecución de HTTP Jobs

Llamamos a tu endpoint según el calendario; tú te centras en el handler. Un constructor de peticiones de verdad — no una simple barra de URL — con los controles que de otro modo tendrías que improvisar alrededor del cron del sistema.

  • Cualquier método — GET, POST, PUT, PATCH, DELETE — con cabeceras propias y cuerpo JSON
  • Variables de plantilla: pon {{var}} en la URL, las cabeceras o el cuerpo, resueltas en el servidor en tiempo de ejecución
  • Organiza los jobs con etiquetas como env:prod o team:backend y luego agrupa y filtra el panel por etiqueta
  • Reintentos configurables con backoff exponencial — y solo en los códigos de estado que elijas
  • Tiempo de espera por job más «saltar si aún está en ejecución», para que un job lento nunca solape al siguiente
  • Zona horaria por job con manejo correcto del DST — planifica en hora local, ejecuta bien todo el año
  • Cada ejecución registrada por completo: estado, cuerpo y duración de la respuesta, conservados para auditoría
  • Ejecutar, pausar o reanudar desde la UI — o sincronizar todo el job con YAML o la CLI
app.steadycron.com/jobs/new
invoice-send

Request

Configure the HTTP request sent on each execution. Use {{variable}} for template substitution.

POST
{{baseUrl}}/v1/invoices/{{invoiceId}}/send
Send
Params Headers 1 Body

Headers

Authorization Bearer {{apiToken}}
Body raw · JSON
{
  "account_id": "{{accountId}}",
  "amount_cents": 4900,
  "send_email": true
}

Valid JSON

Schedule

When it runs — cron or interval, with DST-correct timezones and a live next-runs preview.

Cron Interval

Cron expression

0 9 * * 1-5

Weekdays at 09:00

Timezone

Europe/Berlin

Next runs

Mon 09:00Tue 09:00Wed 09:00Thu 09:00
timeout 30sretries 3skip if still running

Monitorización Heartbeat

Vigila los cron jobs que ya ejecutas, estén donde estén. Tu job nos envía un ping; nosotros vigilamos el reloj. Si el ping no llega — proceso caído, servidor reiniciado, job colgado — te enteras antes que tus usuarios.

  • Un interruptor de hombre muerto para cualquier cron, script o worker — en cualquier lenguaje o shell
  • Haz ping a /start y luego a /success o /fail para medir la duración y detectar jobs que mueren a medias
  • Los periodos de gracia absorben la fluctuación normal: alerta solo cuando una ejecución llega realmente tarde
  • Detecta tres fallos distintos: ejecuciones perdidas, fallos explícitos y jobs bloqueados que nunca terminan
  • Cada control tiene una URL de ping estable — renombra el job libremente y tus scripts siguen funcionando
  • Alertas por email, Slack, Discord, Telegram o webhook — se resuelven solas al recuperarse
  • Agrupa y filtra por etiqueta: un entorno con fallos sube a lo más alto de la lista
  • Una línea para integrarlo: solo haz curl a la URL de ping al final de tu job
app.steadycron.com/jobs

Jobs

New job
Search jobs…
All HTTP Heartbeat
Status Group: env
env:prod 5 jobs 1 failing
weekly-digest-email HTTP 0 9 * * 1 in 2 days 3 days ago
nightly-db-backup Heartbeat 0 2 * * * in 19 h 5 h ago
stripe-reconciliation HTTP 0 */4 * * * in 38 min 3 h ago
cache-warmup HTTP */15 * * * * in 11 min now
search-index-sync Heartbeat */30 * * * * in 6 min 24 min ago
env:dev 3 jobs
seed-test-data HTTP 0 4 * * * in 14 h 10 h ago
preview-env-cleanup Heartbeat 0 */6 * * * in 2 h 4 h ago
trial-expiry-sweep HTTP 0 6 * * * yesterday

Define todo como código

Declara toda tu cuenta — jobs, heartbeats, canales, etiquetas y variables — en un manifiesto YAML versionado. Reconcilia desde la CLI o directamente en CI.

  • Un manifiesto YAML versionado define jobs, heartbeats, canales, etiquetas y variables
  • Adopta una cuenta existente en segundos — steadycron export la convierte en un manifiesto
  • validate → plan → apply, con diffs estilo Terraform que revisas en un pull request
  • --prune elimina lo que quitaste; los namespaces separan de forma segura IaC y jobs manuales
  • IDs estables: renombrar es solo renombrar — sin recrear, y las URLs de heartbeat se conservan
  • Los secretos nunca tocan Git: ${ENV} lo resuelve la CLI, {{template}} el servidor
  • La GitHub Action publica el plan en cada PR y lo aplica al hacer merge
  • Todo lo que hace la CLI es también una API REST — claves con permisos, de solo lectura o completas
steadycron — bash
$ steadycron jobs list
╭────────────────┬───────────┬─────────┬────────────────────┬──────────┬──────────╮
Name Kind Status Schedule Next run Last run
├────────────────┼───────────┼─────────┼────────────────────┼──────────┼──────────┤
weekly-digest http success 0 9 * * 1 (UTC) in 2d 3d ago
nightly-backup heartbeat late 0 2 * * * (UTC) 5h ago
stripe-recon http failure 0 */4 * * * (UTC) in 38m 3h ago
cache-warmup http running */15 * * * * (UTC) in 11m now
search-sync heartbeat success */30 * * * * (UTC) 24m ago
report-export http success 0 6 * * * (UTC) in 14h 10h ago
token-refresh http success 0 */6 * * * (UTC) in 2h 4h ago
trial-sweep http paused 0 6 * * * (UTC) 1d ago
╰────────────────┴───────────┴─────────┴────────────────────┴──────────┴──────────╯
8 job(s).
$ steadycron cron preview "0 9 * * 1-5" --timezone Europe/Berlin
Next 5 fires of 0 9 * * 1-5 (Europe/Berlin):
╭───┬───────────────────────────┬──────────╮
# Fire time (Europe/Berlin) Relative
├───┼───────────────────────────┼──────────┤
1 2026-06-08 09:00:00 in 3d
2 2026-06-09 09:00:00 in 4d
3 2026-06-10 09:00:00 in 5d
4 2026-06-11 09:00:00 in 6d
5 2026-06-12 09:00:00 in 7d
╰───┴───────────────────────────┴──────────╯
$ steadycron jobs run cache-warmup
triggered cache-warmup · 200 OK · 412 ms
$ steadycron validate manifests/production.yaml
manifest valid · 0 errors
$ steadycron plan manifests/production.yaml
~ weekly-digest update retries: 2 → 3
+ invoice-reminder create kind: http · 0 17 * * 5
- legacy-report destroy (absent from manifest)
Plan: 1 to add · 1 to change · 1 to destroy
$ steadycron apply --prune manifests/production.yaml
apply complete · 1 added · 1 changed · 1 destroyed

Preguntas, respondidas

¿Dónde se almacenan mis datos?

Todo funciona en la infraestructura de Hetzner en Alemania, sujeta a la ley alemana. La ejecución principal no utiliza subprocesadores estadounidenses, y hay un DPA de RGPD disponible.

¿Puedo monitorizar cron jobs que se ejecutan en mis propios servidores?

Sí. Añade un heartbeat check y haz que tu job envíe un ping al terminar (un único curl al final de tu script). Si el ping no llega según lo previsto, SteadyCron te avisa. Funciona desde cualquier lenguaje o shell.

¿SteadyCron reemplaza AWS EventBridge o el cron de Cloudflare/Vercel?

Para trabajo HTTP programado, sí. SteadyCron llama a tu endpoint según el horario con reintentos configurables, tiempos de espera y logs completos de petición y respuesta — sin atarte a una nube. También tienes monitorización y alertas en el mismo lugar.

¿En qué se diferencia de Healthchecks.io?

Healthchecks es excelente en monitorización heartbeat. SteadyCron hace las dos partes — ejecuta tus HTTP jobs y monitoriza heartbeats desde un solo dashboard — y está alojado en la UE con flujos de trabajo infra-as-code integrados.

¿Hay un plan gratuito?

Sí — 4 HTTP jobs y 12 heartbeat checks, gratis para siempre, sin tarjeta de crédito. Los planes de pago empiezan en 10 €/mes.

¿Puedo definir mis jobs como código?

Sí. Define los jobs en un manifiesto YAML y sincronízalos con steadycron sync jobs.yaml mediante la CLI, o usa la API REST directamente. Sin click-ops, sin desvíos entre entornos.