Skip to main content
rootly-catalog-sync is a standalone CLI tool that reconciles external sources of truth into Rootly’s Catalog. It pulls data from your existing systems — GitHub repos, Backstage, internal APIs, CSV files, or any command — and syncs it one-way into Rootly, keeping services, teams, and metadata up to date automatically.
Rootly Catalog

Why use Catalog Sync?

  • Single source of truth — your service catalog lives in GitHub, Backstage, or a database. Rootly mirrors it automatically.
  • No manual data entry — add a service to your repo, it appears in Rootly on the next sync.
  • Safe by default — deletes are opt-in, empty sources abort, prune ratio thresholds prevent mass deletion.
  • Terraform-style workflowplan to preview, apply to execute, status to check drift.

Install

Quick start

Authentication

Two methods are supported, in priority order:

API key (CI / non-interactive)

Create an API key at Settings → API Keys in your Rootly dashboard.

OAuth 2.0 (interactive)

If ROOTLY_API_KEY is set, it always takes precedence over OAuth tokens.

Configuration

The sync tool uses a declarative config file (v2 format) that defines sync entries — each entry connects a source to a catalog or native resource target.
Config files are detected by extension: .yaml (default), .jsonnet, or .hcl. Credentials use $(ENV_VAR) substitution.

Sources

Inline source

Local source

GitHub source

Omit repos to scan all repositories in the org. Set archived: true to include archived repos.

Backstage source

Exec source

GraphQL source

CSV source

The first row is used as field names. Each subsequent row becomes an entry.

URL source

HTTP source

Output targets

Each sync entry uses to: to specify the target. The value of to: determines whether entries go to a custom catalog or a native Rootly resource.
  • Native resource: use a lowercase type name — to: service, to: team, to: functionality, to: environment
  • Custom catalog: use the catalog display name — to: "Services", to: "Tiers"

Custom catalog

Creates entities in a named Rootly catalog with arbitrary fields.

Native resources

Sync directly to built-in Rootly resource types.
For native resources, known attributes (like description, pagerduty_id, github_repository_name) are set directly on the resource. Custom properties are auto-created on first sync for SDK-supported kinds (text, boolean, group, service, etc.). Reference properties are auto-created when the referenced catalog exists.

Custom properties

Native resources (services, teams, functionalities, environments) support custom properties that extend the built-in attributes. These properties are managed automatically during sync.

Auto-created properties

Text properties are auto-created on first sync. Simply include them in your map: and they will appear on the resource:

Reference properties

Reference properties link native resources to catalog entities. To use them, first sync the referenced catalog, then reference it in the native resource mapping. For example, to link services to a “Tiers” catalog:
tiers.yaml
rootly-catalog-sync.yaml
The reference: Tiers shorthand tells the sync tool to resolve the human-readable tier name to the corresponding catalog entity UUID. Matching is case-sensitive and compares the field value against the catalog entity’s name (not external_id). The referenced catalog (“Tiers” in this example) must exist — sync it in an earlier sync entry so it is available when the service entry runs.

Template syntax

Field mappings use Go template syntax to transform source entries into output fields.

Field access

Conditionals

Templates are compiled with missingkey=error — a missing field in the source data causes an immediate error rather than a silent empty string.

Commands

Safety guarantees

  • Deletes are opt-in--allow-prune required, off by default
  • Empty source aborts — never wipes a catalog on a source failure
  • Prune ratio threshold — aborts if deletes exceed 20% of live entities (configurable via --prune-threshold)
  • Manual entries are safe — only entries with external_id (created by sync) are prunable
  • Order: create/update first, delete last — no window where entries are missing
  • Plan freshnessapply validates that live state hasn’t changed since the plan was created

CI/CD integration

GitHub Actions

Dry-run on PRs

Nightly drift detection

Kubernetes deployment

Deploy catalog sync to Kubernetes using the official Helm chart:
By default the chart creates a CronJob that runs every 30 minutes. To run in watch mode (continuous sync loop):
To include local data files referenced by your config, use a values file:

Environment variables

Interactive TUI

The tui command launches a full-screen terminal UI for reviewing and selectively applying changes:
  • Browse changes with colored badges (CREATE/UPDATE/DELETE/NOOP)
  • Toggle individual changes with space, expand field diffs with enter
  • Filter by operation type (c/u/d) or search (/)
  • Detail pane shows full entity fields on wide terminals
  • Apply only selected changes with A

Resources