Back to Blog
2026-03-19 โ€ข 14 min read

GitHub Actions Monitoring: How to Get Alerts When Cron Jobs Fail

Monitor your scheduled GitHub Actions workflows with QuietPulse heartbeat. Get instant alerts through Telegram or webhooks when a cron job misses its run or fails silently.


Why Monitor GitHub Actions Cron Jobs?

GitHub Actions is a powerful CI/CD platform, but its built-in monitoring has a critical gap: it only alerts on workflow failures, not on missed runs.

Consider these scenarios:

  • Cron syntax error โ€” workflow never triggers, no error reported
  • Runner unavailable โ€” scheduled time passes, job doesn't start
  • Silent exceptions โ€” job starts but crashes before actual work

These silent failures can break deployments, miss backups, or stall data pipelines โ€” and you won't know until it's too late.

Solution: Heartbeat monitoring for GitHub Actions. A simple HTTP ping after each successful run ensures you're notified the moment a scheduled task goes silent.


How Heartbeat Monitoring Works

The pattern is elegantly simple:

  1. Each scheduled workflow sends a GET request to a unique QuietPulse endpoint after successful completion
  2. QuietPulse expects these pings at your configured interval (matching the cron schedule)
  3. If a ping is missed โ†’ QuietPulse sends an alert through your configured channels

It's a dead man's switch for your cron jobs.

text
+-------------------+     +--------------------+     +---------------------+
| GitHub Actions    | --> | QuietPulse         | --> | Alert on Miss       |
| (cron job)        |     | /ping/:token       |     | (Telegram/Webhook)  |
+-------------------+     +--------------------+     +---------------------+

Step-by-Step: Add Monitoring to Your GitHub Actions Workflow

1. Create a Heartbeat Job in QuietPulse

  1. Sign up at quietpulse.xyz
  2. Click "New Job"
  3. Configure:
    • Name: e.g., "Nightly Backup"
    • Expected interval: match your cron schedule (e.g., 1 hour for 0 * * * *)
    • Grace period: allow small delays (e.g., 5 minutes)
  4. Copy the generated Ping URL (it looks like: https://quietpulse.xyz/ping/abc...)
    • The token is the last segment (abc...)

2. Add the Ping Step to Your Workflow

Add a step at the end of your job (only on success):

name: Nightly Backup

on:
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM

jobs:
  backup:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run backup
        run: |
          # Your backup logic here
          pg_dump ...

      - name: Send heartbeat to QuietPulse
        if: always()  # Or success() to only ping on success
        uses: vadyak/quietpulse-actions@v1
        with:
          endpoint_token: ${{ secrets.QUIETPULSE_TOKEN }}
          grace_period_minutes: 5

Important: Use if: always() if you want to ping even on failure (to detect if the job didn't complete), or if: success() to only ping when the job succeeded. For true heartbeat monitoring, you typically want only on success โ€” a missing ping means the job didn't finish.

3. Store Token in GitHub Secrets

  1. Go to your repository Settings โ†’ Secrets and variables โ†’ Actions
  2. Click "New repository secret"
  3. Name: QUIETPULSE_TOKEN
  4. Value: paste the token from QuietPulse (the last part of the URL)
  5. Click Add secret

4. Configure Alerts in QuietPulse

In your QuietPulse job settings, configure Telegram notifications, webhooks, or both to receive alerts when the heartbeat is missed.


Complete Examples

Node.js Project with npm Script

name: Deploy Production

on:
  schedule:
    - cron: '*/30 * * * *'  # Every 30 minutes

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Run migrations
        run: npm run migrate

      - name: Deploy to production
        run: npm run deploy

      - name: Notify QuietPulse
        if: success()
        uses: vadyak/quietpulse-actions@v1
        with:
          endpoint_token: ${{ secrets.QUIETPULSE_DEPLOY_TOKEN }}

Python Cron Job

name: Daily Data Processing

on:
  schedule:
    - cron: '0 3 * * *'  # 3 AM daily

jobs:
  process:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Process data
        run: python scripts/process.py

      - name: Send heartbeat
        if: success()
        uses: vadyak/quietpulse-actions@v1
        with:
          endpoint_token: ${{ secrets.QUIETPULSE_PROCESS_TOKEN }}

Laravel / PHP Project

name: Laravel Scheduler

on:
  schedule:
    - cron: '* * * * *'  # Every minute (Laravel handles schedule internally)

jobs:
  laravel-schedule:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          extensions: mbstring, pdo_mysql

      - name: Install Composer dependencies
        run: composer install --no-dev --optimize-autoloader

      - name: Run Laravel scheduler
        run: php artisan schedule:run

      - name: Heartbeat
        if: success()
        uses: vadyak/quietpulse-actions@v1
        with:
          endpoint_token: ${{ secrets.QUIETPULSE_LARAVEL_TOKEN }}

Best Practices for GitHub Actions Monitoring

1. Match Intervals Precisely

Set the expected interval in QuietPulse to match your cron schedule exactly:

Cron Expression Expected Interval Grace Period
*/5 * * * * 5 minutes 1-2 minutes
0 * * * * 1 hour 5-10 minutes
0 2 * * * 1 day 30 minutes

2. Only Ping on Success

Use if: success() to send the heartbeat only if all previous steps succeeded. This ensures that a missing ping indicates a real failure.

- name: Heartbeat
  if: success()  # Critical!
  uses: vadyak/quietpulse-actions@v1
  with:
    endpoint_token: ${{ secrets.QUIETPULSE_TOKEN }}

3. Use Separate Tokens per Job

Don't reuse the same endpoint token across unrelated workflows. Each job gets its own QuietPulse endpoint so you can identify exactly which task failed.

4. Set Appropriate Grace Periods

The grace period accommodates normal variations (GitHub runner queue delays, network latency). Too short โ†’ false alarms; too long โ†’ slow detection.

Recommended:

  • Short intervals (5-15 min): 20-30% grace
  • Long intervals (daily): 10-30 minutes

5. Monitor the Monitor

QuietPulse itself is monitored, but if you're self-hosting, set up a secondary heartbeat for the QuietPulse service (e.g., ping an external service every minute).


Action Inputs Reference

Input Required Default Description
endpoint_token โœ… Yes โ€” QuietPulse endpoint token (from job settings)
grace_period_minutes โŒ No 5 Grace period before marking as missed
timeout_seconds โŒ No 10 HTTP request timeout in seconds

Outputs

Output Description
status Result: success, failed, or error
http_status HTTP response code from QuietPulse
message Success message or error details

You can use these outputs in subsequent steps:

- name: Check heartbeat result
  id: heartbeat
  uses: vadyak/quietpulse-actions@v1
  with:
    endpoint_token: ${{ secrets.QUIETPULSE_TOKEN }}

- name: Fail if heartbeat failed
  run: |
    if [ "${{ steps.heartbeat.outputs.status }}" != "success" ]; then
      echo "โŒ Heartbeat failed!"
      exit 1
    fi

Troubleshooting

Issue Likely Cause Fix
404 Not Found Invalid token or job doesn't exist Create the job in QuietPulse, copy token correctly
403 Forbidden Token expired or wrong Generate a new endpoint token in QuietPulse
429 Too Many Requests Rate limit exceeded Upgrade QuietPulse plan or reduce ping frequency
Action times out Network issues or QuietPulse down Increase timeout_seconds, check QuietPulse status
Workflow doesn't trigger Cron syntax error Validate cron expression at crontab.guru
No Telegram alerts Telegram not connected in QuietPulse Connect Telegram bot in job settings
No webhook alerts Webhook not configured or receiver failed Check webhook URL, test delivery, and receiver logs

Comparing GitHub Actions Monitoring Solutions

Feature QuietPulse (this action) UptimeRobot GitHub Status API
Monitors cron triggers โœ… โŒ (only checks URL) โŒ
Free tier โœ… (5 jobs) โœ… (50 monitors) โœ… (limited)
Telegram alerts โœ… โŒ โŒ
Webhook notifications โœ… โœ… โŒ
No external dependencies โœ… โŒ โŒ
Self-hosted option โŒ โŒ N/A
Easy setup โœ… 2-minute config โœ… โŒ (custom script needed)

QuietPulse is the only simple solution that actually monitors whether your GitHub Actions cron jobs ran โ€” not just whether the server is up.


Advanced: Multi-Channel Alerting

QuietPulse supports both direct Telegram alerts and webhook notifications. For example, you can forward failures into Slack through your own webhook-based automation:

- name: Heartbeat
  if: failure()  # Only on failure
  uses: vadyak/quietpulse-actions@v1
  with:
    endpoint_token: ${{ secrets.QUIETPULSE_TOKEN }}

- name: Alert Slack on failure
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "โŒ Cron job failed: ${{ github.workflow }}",
        "channel": "#alerts"
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Next Steps

  1. Install the heartbeat action in your critical workflows
  2. Set up Telegram alerts, webhooks, or both in QuietPulse dashboard
  3. Add multiple endpoints for different jobs (separate tokens)
  4. Explore other integrations: n8n, Slack, custom webhook flows
  5. Read related guides:

Ready to never miss a cron failure?
Sign up for QuietPulse and protect your scheduled tasks in minutes.