What changed

Every change, not just the deploys

A feature flag flipped, a config value edited, a dependency upgraded, a migration run: ForgeOps puts them on one timeline with your deploys, and shows the ones just before an issue started right on the issue.

What changed, right on the issue

Plenty of breakages have no deploy behind them: a flag turned on for everyone, a timeout lowered in config, a library bumped along with an unrelated fix. When an issue starts, its verdict lists the changes recorded in the two hours before it, with how long before and who made them. A gateway timeout that began three minutes after gateway_retry_v2 went to 100% of checkouts says so on the first screen.

They're labeled potentially relevant, because that's all ForgeOps knows: they happened nearby, not that they caused anything. An incident's timeline includes the same changes in order with everything else, and the verdict text in on-call pages carries an "Also changed" line.

An issue's verdict listing what changed just before it started, labeled potentially relevant: the gateway_retry_v2 flag turned on for 100% of checkouts 3 minutes before, and a stripe upgrade and a new environment variable detected after the deploy

The flag flip three minutes before the timeouts, on the issue itself.


One timeline of every change

Each project has a Changes page: every deploy and every recorded change, newest first, filterable by kind (deploys, feature flags, config, migrations, dependencies, infrastructure) and by environment. A dependency upgrade lists each package with its old and new version, and a change detected at startup says so.

It's the list to scan when the question is "what's different since it last worked?", without asking in chat who touched what.

A project's Changes page listing a feature flag change, a new environment variable and a stripe upgrade detected at startup, and the deploys before them

Deploys and every other change, in one list.


Detected at startup

Each time your app starts, the server SDKs send ForgeOps a short description of what's running: the runtime version, dependency versions where the language keeps a reliable list of them (Ruby, Python, Node.js, PHP, Go, and Elixir), and for Rails the database schema version, so a migration shows up too. ForgeOps compares it with the last start and records only what's different.

A hundred processes starting the same build record each change once, and a mix of old and new processes during a rolling deploy isn't read as changes back and forth. Environment variables are opt-in, and only their names are ever sent, never their values; names that differ from host to host, like HOSTNAME or PORT, are left out so a fleet doesn't look like it keeps changing.


Recorded from your code, CI, or anything else

Every ForgeOps SDK has a record_change call (recordChange or RecordChange, in each language's own style) that takes a kind, a title, and optional details, actor, and link. Call it from your flag or remote config client's change callback and every flip lands on the timeline. It never blocks and never throws.

From CI, infrastructure tooling, or a script, send the same thing to POST /api/v1/changes with the project's API key or upload token, up to 50 at once. Give a change an id and a retried request records it once. Change tracking is included on the Business plan and up.


See it on your own data

Free plan included, no credit card required.

Get started free