/ guides / maintenance-windows

Maintenance windows: silence alerts, keep checking

How maintenance windows stop deploy alerts while checks keep running: one-off or recurring, timezones, uptime, and opening one from CI or an agent.

Updated

A maintenance window tells your monitoring that downtime in a given period is planned, so a deploy, a database upgrade or a reboot does not page anyone. Fettle is uptime monitoring for developers, and its maintenance windows keep checking every covered monitor but open no incident and send no alert while the window is in effect. Windows are one-off or recurring, follow your timezone through daylight saving changes, and are available from Pro. You can open one from the dashboard, the API (from CI right before a deploy) or an AI agent.

What happens to a monitor during a maintenance window?

Checks keep running on their usual schedule and from the usual regions. Each result is stored and marked with the window that covered it, and the monitor's status still changes, so the dashboard shows a real DOWN if the deploy breaks something. What the window suppresses is the incident and every alert that would follow it: down, reminder and recovery.

If the monitor is still failing when the window ends, Fettle does not wait for a fresh streak of failures. The first failed check after the window opens an incident and sends the down alert, with the incident starting at that check, not at some point inside the window. A deploy that went wrong reaches you within one check interval of the window closing.

Two things a window does not suppress. SSL expiry warnings are not incidents, so they arrive as usual. And a window covers monitors, not heartbeats: pause the heartbeat of a job that will not run, as the heartbeats docs describe.

Which monitors does a window cover?

Either the whole organization or a list of monitors. An organization-wide window covers every monitor, including ones created after the window. A monitor window covers only the monitors you pick, and needs at least one. There is no tag-based scope; to cover a group of monitors, select them in the form, or pass their ids through the API.

Several windows can overlap. A monitor is in maintenance when any enabled window that covers it is in effect.

How do recurring maintenance windows work?

A window has a start, a length and, optionally, a repeat schedule. The dashboard builds the common ones: daily, weekly on the days you pick, monthly or yearly, every N of those, ending on a date, after a number of occurrences, or never. The API also takes less regular schedules, such as the last Friday of every month.

Hourly and minute-level frequencies are refused.

Each occurrence lasts from one minute to 28 days. Before you save a recurring window, the form, the API and the MCP tools can preview its next occurrences, so a schedule that lands on the wrong day shows up before it silences anything.

Editing a window keeps a history of its earlier schedules, and check results keep a reference to the window that covered them, so you can tell afterwards why an outage did not alert.

How does a maintenance window handle timezones and daylight saving?

Every window runs in a named timezone, by default your organization's. The start is a local wall-clock time in that zone, and a repeating window keeps that local time: a weekly window at 03:00 on Sunday stays at 03:00 after the clocks change, rather than drifting to 02:00 or 04:00 the way a schedule kept in UTC would.

If you send the start through the API, send it without an offset or Z and name the zone in timezone. A start with an offset is refused instead of being guessed at.

How does maintenance affect uptime and the status page?

Time inside a window counts as up. Fettle calculates uptime as observed time minus confirmed outages, and a window opens no outage, so planned downtime does not lower the figure on the dashboard, the API, badges or the status page. The 99.9% uptime guide explains what the figure measures.

On a status page, a component whose monitor is in maintenance shows "Maintenance" instead of an outage. The page banner shows maintenance too, unless another component is down or degraded at the same time, in which case the worse state wins.

Pause or maintenance window: which one to use?

Use a maintenance window for planned work you expect to end: a deploy, a migration, a reboot. Use pause when you want a monitor to stop entirely, for example a service you are retiring. Pausing stops checks, closes any open incident without an alert, and stays in effect until someone resumes the monitor.

The practical differences:

  • A paused monitor collects no data, so you cannot see whether the deploy actually broke anything, and the paused hours are left out of uptime rather than counted.
  • A pause has no end. Forget to resume and the monitor stays silent through the next real outage. A window ends on its own, even when the CI job that opened it crashed halfway through.
  • A window can cover the whole organization in one call. Pausing works monitor by monitor, or in bulk by id.

How do I open a maintenance window from CI before a deploy?

Create a window with a write-scoped API key right before the deploy step, and delete it right after. POST /v1/maintenance-windows returns the window with its id; DELETE /v1/maintenance-windows/{id} ends it at once. Give the window a length a bit longer than your slowest deploy, so it still closes if the job dies before cleanup.

A GitHub Actions job that does this, with the key stored as a repository secret as GitHub's guide to secrets describes:

- name: Open a Fettle maintenance window
  id: maintenance
  env:
    FETTLE_API_KEY: ${{ secrets.FETTLE_API_KEY }}
  run: |
    start=$(jq -nr 'now - 60 | strftime("%Y-%m-%dT%H:%M:%S")')
    id=$(curl -fsS -X POST https://api.fettle.sh/v1/maintenance-windows \
      -H "Authorization: Bearer $FETTLE_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"name\": \"Deploy ${GITHUB_SHA::7}\", \"scope\": \"ORG\", \"dtstart\": \"$start\", \"timezone\": \"UTC\", \"duration_minutes\": 20}" \
      | jq -r .id)
    echo "id=$id" >> "$GITHUB_OUTPUT"

- name: Deploy
  run: ./deploy.sh

- name: Close the maintenance window
  if: always() && steps.maintenance.outputs.id != ''
  env:
    FETTLE_API_KEY: ${{ secrets.FETTLE_API_KEY }}
    WINDOW_ID: ${{ steps.maintenance.outputs.id }}
  run: |
    curl -fsS -X DELETE "https://api.fettle.sh/v1/maintenance-windows/$WINDOW_ID" \
      -H "Authorization: Bearer $FETTLE_API_KEY"

The start is a minute in the past so that a runner clock slightly ahead of Fettle's does not leave the first seconds of the deploy uncovered. jq computes it in UTC the same way on Linux and macOS runners, and the window id reaches the shell through env rather than being pasted into the script. To cover only the services being deployed, use "scope": "MONITOR" with "monitor_ids": [...]. A recurring window takes an extra rrule field. GET /v1/maintenance-windows/active lists what is silenced right now, which is handy as a check at the end of a pipeline.

Keys, scopes and the per-minute limit all of an organization's keys share are in the API keys docs; every endpoint is listed on the uptime monitoring API page.

Can an AI agent schedule maintenance for me?

Yes. Over MCP, an agent like Claude or Codex can create, preview, edit and delete windows with the same rules as the API: create_maintenance_window, preview_maintenance_window, list_active_maintenance and the rest. That makes "silence the API monitors while I run this migration" a sentence rather than a form:

Open a 45-minute maintenance window on every monitor tagged service:api, starting now.
Every Sunday at 03:00 Berlin time we restart the database for 30 minutes. Preview that
schedule, then save it as a maintenance window for the db monitors.
Is anything silenced right now?

The agent finds the monitors, previews a recurring schedule before saving it, and tells you what it created. Setup for Claude, Codex and other clients is in the AI agents guide.

Limits worth knowing

Maintenance windows start on Pro; the pricing page has the full plan comparison. A window does not cover heartbeats and does not suppress SSL expiry warnings. Recovery alerts are suppressed during a window like down alerts, so a monitor that fails and recovers inside the same window sends nothing at all. To check what reached your team outside maintenance, see where alerts go. The rest of the cluster is in the guides, starting from the uptime monitoring overview.

Questions

Do checks stop during a maintenance window?
No. Fettle keeps checking every covered monitor and records the results, marked with the window that covered them. Only incidents and alerts are suppressed while the window is in effect; nothing is queued for later.
Does downtime during a maintenance window count against uptime?
No. Time inside a window counts as up, because no incident opens there. If the monitor is still down when the window ends, an incident opens from the first failed check after it.
Do maintenance windows cover heartbeats?
No. A window covers monitors only. If a cron job will not run during planned work, pause its heartbeat before the work and resume it afterwards, so the missing ping does not alert.

Start monitoring in a minute

The free plan checks up to 20 monitors as often as every 3 minutes from 1 region, and emails you when one breaks. See pricing for the paid intervals, or follow the quickstart to do it from the API.