Migrating to Vigil

A SUMMARY OF docs/MIGRATION.md, WHICH SHIPS IN THE REPOSITORY WITH THE FULL PER-TYPE TABLES. PUBLISHED SO YOU CAN JUDGE THE MOVE BEFORE YOU PAY.

Vigil reads the monitors you already have and creates them here, so switching does not mean retyping your configuration. Fifteen monitoring systems can be read: fourteen over the vendor's own API, and Uptime Kuma from a copy of its database. The count is not the point. The point is that nothing leaves your old system without a line on the report saying what became of it.

Where you can come from

Over the vendor's own API, with a token you paste:

  • Better Stack (Better Uptime)
  • Pingdom
  • UptimeRobot
  • StatusCake
  • Datadog Synthetics
  • Checkly
  • New Relic Synthetics
  • Grafana Cloud Synthetic Monitoring
  • Uptime.com
  • updown.io
  • Hyperping
  • Healthchecks.io
  • Cronitor
  • Oh Dear

Uptime Kuma is the fifteenth and arrives differently: it is a SQLite file rather than an account, so you upload a copy of kuma.db and Vigil opens it read-only. Its compatibility is documented column by column in docs/KUMA-IMPORT.md, and the comparison page covers the rest.

The import screen names the exact credential each source needs and the scope it has to carry. Several of these vendors publish no read-only scope at all; where that is true the screen says so, so you can create a token for the migration and revoke it afterwards. Every request this importer makes is a read: GET, apart from the GraphQL query New Relic's API needs, which is still a read.

The flow

  1. Choose a source under Settings, Import.
  2. Paste the credential. It authenticates the read and then goes out of scope. Nothing writes it to the database, to a log or to the report, and the transport that holds it never gives it back.
  3. Check what will be imported. Vigil reads the account, builds every monitor, validates it, inserts it, lets Postgres check every constraint, and then rolls the whole transaction back.
  4. Read the preview. It lists everything that will not be imported with the rule that refused it, and everything that will be imported with something changed.
  5. Import. The same work, with the transaction kept. It reads the source a second time rather than holding your configuration on a server between the two clicks, so anything created there in between is in the final report and not in the preview.
  6. Keep the report. It is the record of what moved and what did not.

Importing needs the owner or admin role, because it creates monitors and the status pages they appear on. A second import from the same source does not duplicate what the first one brought: a check is matched on its type, URL and name, and a group on its parent and name. Rename an imported monitor in Vigil and a re-import treats it as new.

What comes across

Where the source stores it and Vigil can hold it, all of this moves:

  • Name. Cut to 100 characters, and the cut is reported.
  • Paused state. A monitor paused in the source arrives paused, and says so on its line.
  • URL, hostname and port. Credentials written into a URL are stripped before it is stored, and the removal is reported without the value.
  • Check interval and timeout. Clamped to Vigil's bounds, and the clamp is reported. Sources that store no timeout get Vigil's default.
  • HTTP method. GET and HEAD. Anything else is refused rather than issued as a GET, which would watch something the source never watched.
  • Expected status code. One code carries exactly. A list or a range is reported: Vigil holds one, or none, in which case any 2xx or 3xx passes.
  • Body and JSON assertions. The keyword and its inversion. A JSON expression is rewritten as Vigil's dotted path when it names one fixed location.
  • DNS record type and value. Where the source stores a record type. Sources that do not are refused rather than asked for a record nobody chose.
  • Certificate expiry. The warning threshold, clamped to 1 to 365 days.
  • Retry policy. Converted into Vigil's failure window: how long a monitor must be failing before an incident opens.
  • Groups and folders. Created as Vigil group monitors, outermost first, and reused rather than duplicated on a second import.
  • Status pages. Where the adapter reads them. The slug becomes the public URL and is rewritten if it has to be.
  • Heartbeats. With their grace period, and always with a new token.

What no migration carries

These are properties of Vigil rather than of any one source, so they are not gaps that a later adapter closes:

  • Credentials. No password, bearer token, header value or API key is copied out of a monitoring account, and the model the importer builds has nowhere to put one. A check that authenticated will not authenticate after the move; the report names the field so you know which ones to fix.
  • Request headers and bodies. Vigil's HTTP check issues GET or HEAD with its own headers. Header names are reported so you know what the endpoint expected. There is nowhere in the migration model to put a value, so none crosses.
  • Tags. Vigil has no monitor tags. Each distinct tag gets one report line naming the checks that carried it. A group is the nearest thing and is not the same thing.
  • Maintenance windows. Not carried. Vigil has windows of its own in the commercial edition, but a schedule, its recurrence rule and its time zone are an account-level record this importer reads rather than recreates, and a window imported wrong silences the wrong hours. Declare them again after the move.
  • Alert routing. Every one of these systems attaches contacts or escalation policies to individual checks. Vigil decides who is told by notification channel, escalation policy and, in the commercial edition, a routing policy assigned to the workspace, a service or one monitor. None of those is a per-check attachment, and no credential is copied out of the source account anyway. Set the channels up under Settings, Notifications and the imported monitors use them.
  • Probe locations. Region names do not transfer. Vigil checks from the worker that runs it, or from a remote probe you enroll. The report names the regions each check ran from.
  • Check history. Vigil's uptime is duration-weighted over observations it made itself and hashed into its own ledger, so importing another system's history would put unverifiable rows in a chain whose whole purpose is that every row is verifiable.
  • Anything defined as code. Browser journeys, k6 scripts, Playwright tests, recorded transactions, multistep chains. These are not lossy, they are unmigratable, and every one of them is reported by name. Vigil does have journeys of its own, and that is why these are refused rather than approximated: a Vigil journey is a list of typed steps with no loops, no branching and no expressions, so a script that uses any of those has no translation.

Support is per check type, not per vendor

A source appearing above is not a promise that every monitor in it arrives intact. Support is decided one source check type at a time, and a type with no honest Vigil equivalent is refused rather than approximated into a monitor that watches the wrong thing or never passes. The full table in docs/MIGRATION.md has one row per source check type, what it becomes, and what changed on the way. It is generated from the adapters themselves rather than written by hand.

Read the preview before you commit it. That is what it is for: it is the same work the import does, and the only difference is whether the transaction is kept.

Sources Vigil will not claim to support

Each of these is a decision, not a backlog item. Each was reached by reading the vendor's own published API, and each says what would have to change for the answer to change.

  • Sematext Synthetics. The read API does not return the check's request definition: url, method, headers and body are writable and not readable. An importer cannot reconstruct even the target of an HTTP monitor, so any adapter would have to ask you to retype every URL, which is not a migration.
  • Atlassian Statuspage. Not a monitoring system. It holds pages, components, incidents and subscribers and never probes anything, so there are no checks to migrate. Recreate the page as a Vigil status page and add monitors to it.
  • Freshping. Retired by Freshworks, which deletes account data after the sunset date, so there is no live account left to read.
  • Monitis. The service and its API host no longer resolve. There is nothing for an adapter to connect to.

Large migrations

Past about a hundred monitors an import is a job rather than a click: naming, grouping and which checks are worth keeping are decisions, and the report is what you make them from. Ask about a migration if you would rather not do that part alone.