Set up Production Impact
Production Impact ranks live downstream consumers by real traffic, flags migration lock risk before it ships, and correlates a touched path with past production incidents — all from read-only metadata, never a database password and never a scan of your rows. Nothing here is required to get a brief: Change Analysis runs on every pull request with zero setup. This guide covers what Production Impact needs, and why each piece is a declaration rather than a guess.
It does not cover Visual Review, which has its own setup guide.
1. Declare which environment is production
Do this first — everything else is scoped by it. Most observability
platforms hold more than one environment that looks like production: a
blue/green pair, a -v2 migration in progress, a staging tier someone
renamed once and never renamed back. Nothing in the vendor's data reliably
tells them apart, and Production Impact reading the wrong one doesn't fail —
it produces a plausible, confidently-stated blast-radius number for the
wrong environment, in every reviewer's brief, indefinitely.
So LGTY never infers this. On the Connections page, each connection names the
environment its metrics come from — for example prod-v2, if that's what
your platform calls it. A connection that hasn't declared one is shown as its
own state, distinct from both "connected" and "not connected": the credential
is stored, but nothing is queried against it until the environment is named.
2. Connect a metadata source
Two channels; pick per source. Both are read-only and revocable.
Tier 1 — a scoped read-only token. Paste a token for an observability platform you already run (Datadog, Grafana Cloud, New Relic, Honeycomb, Dynatrace). LGTY reads dependency and traffic metadata through it and pre-indexes on a cadence — not per pull request. Fastest option, usually around five minutes, and it reuses access you already granted the vendor.
Tier 2 — the lgty GitHub Action, OIDC. Add a step to a scheduled CI job.
It snapshots metadata inside your own perimeter and uploads estimates only,
authenticated by OIDC — no long-lived token for LGTY to hold at all. Best
when you can't grant a standing token, or don't run a hosted APM.
- uses: lgty/collect-metadata@v1
with:
oidc: true
sources: pg_stat,otel
Every claim built on either channel carries its own coverage percentage and snapshot age. A pull request never triggers a live query against your systems — it's a lookup against the index LGTY already built on its own schedule.
3. Declare your database, for migration safety
Add a production_impact.database block to lgty.yml:
production_impact:
database:
engine: postgres
version: "15"
migrations:
- db/migrate/*.rb
engine, version, and migrations (repo-relative globs to your migration
files) are all required, and none of them have a conventional-path default.
This is a claim about your production database — the same reason the
environment above is declared, not detected: a wrong guess here produces a
wrong lock-class or rewrite-risk finding, stated with the same confidence as
a right one. If this block is missing or doesn't parse, migration safety
declares itself not applicable rather than guessing an engine.
Once it's set, static migration analysis — lock class, rewrite risk, missing or irreversible rollback, with the offending DDL as the receipt — runs on every pull request touching a matching migration file. It needs no database connection and no environment declaration; it's pure static analysis against the DDL in the diff.
4. Connect a narrowly-scoped CI role, for row estimates
The static check above works without this — it'll tell you a migration takes
an ACCESS EXCLUSIVE lock whether or not it can also tell you the table has
2.1 million rows. To get the row estimate too, run the lgty action in CI
against a database role scoped to read table structure and size — never your
data, never a table scan, never a live SELECT count(*). Row counts come
from your database's own cheap statistics (pg_class.reltuples,
n_live_tup, or the MySQL equivalent), labeled as an estimate with the
snapshot age it was taken at.
5. Optional — connect PagerDuty for incident correlation
A read-only API token, plus your own declaration of which PagerDuty service
ids map to which of your services — LGTY never infers that mapping. Until
it's connected, a brief states past-incident correlation as not connected,
never as a clean incident history. Metadata only travels through this
connection: incident title, timestamp, affected service, severity — never a
postmortem body.
What each step buys you
- Nothing beyond install — Change Analysis on every PR; Production Impact
paths read
uncovered. - Environment declared + a metadata source connected — downstream consumers, ranked by real traffic, with coverage and snapshot age.
- +
production_impact.databasedeclared — migration lock class, rewrite risk, and rollback findings, with no connection required for this part. - + a scoped CI database role — the same migration findings, now with row-count estimates attached.
- + PagerDuty connected — past-incident correlation for touched paths,
instead of
not connected.
Current boundaries
This covers environment-scoped connections, tier-1 token and tier-2 CI ingestion, static migration analysis independent of any connection, row estimates from cheap database statistics, and incident correlation sourced from a connected on-call platform.
It does not infer which environment is production, does not infer a
database engine or version, does not infer PagerDuty service mappings, and
does not run a live query against your systems on a pull-request event —
every finding comes from a pre-built index, refreshed on its own schedule.
Absence of a connection is never rendered as "no impact" — it's declared
uncovered, and stays that way until you connect one.