The map
The map shows what runs where, read off the providers you connect, and how each piece depends on the others. Where the catalog records who owns a service, the map records what that service runs on, and the two meet when you link them.
Open it from Map in the sidebar, under Respond.
What goes on the map
Section titled “What goes on the map”Each connection to a provider that runs or holds infrastructure puts what it reaches on the map, with a link to the resource’s page on the provider where it has one.
| Connection | What it puts on the map |
|---|---|
| AWS | ECS services, App Runner services, Elastic Beanstalk environments, Lambda functions, EC2 instances, RDS databases and CodeBuild projects in each region the connection reads, and the CodePipeline pipelines, CodeDeploy deployment groups and CloudFormation stacks that release them, each linked to what it releases. A CodeBuild project shows how its newest build ended, or that it is building |
| Azure | App Service and Function apps, Container Apps and the hostnames they serve, Azure SQL databases, PostgreSQL flexible servers and container registries |
| Azure DevOps | The repositories and pipelines of the projects the connection reads, each pipeline linked to the repository it builds, and what the repositories’ infrastructure files define |
| Bitbucket | The workspace’s repositories, and what their infrastructure files define |
| CircleCI | Each project the token reaches, as a pipeline, linked to the repository it builds when CircleCI says which |
| ClickHouse | Each service in the organizations the connection reaches, as a database, and the ClickPipes that load data into it, as pipelines |
| Cloudflare | Zones and their hostnames, Workers, Pages projects, R2 buckets, D1 databases, KV namespaces, queues, Hyperdrive configurations, Tunnels, load balancers and their pools, and Access applications |
| Convex | The deployment, under its project |
| DigitalOcean | Apps, the domains they serve and the repositories they build from, Droplets and databases |
| Fly.io | Apps with their machines and the hostnames their certificates cover, and Managed Postgres clusters with the apps attached to them |
| GitHub | The repositories the connection sees, and what their infrastructure files define |
| GitLab | The projects the token sees, and what their infrastructure files define |
| Google Cloud | Cloud Run services and the addresses they serve, Cloud Run jobs, Cloud SQL instances, Compute Engine instances, GKE clusters, and Cloud Deploy delivery pipelines with a release flow for each stage, linked to the Cloud Run services and jobs they released |
| Kubernetes | Workloads, services and ingresses in the connected namespaces, with what serves what |
| Modal | The environment’s deployed apps |
| Neon | Projects, their branches, the computes serving each branch, the databases on it and its Neon Functions |
| Netlify | Sites, the domains they serve and the repository each builds from |
| Northflank | Services, build services, databases and jobs in each project the connection reads, the repository each one builds from, the domains on each service’s public ports, and the project’s workflows, its pipelines and the release flow of each pipeline stage, each linked to what it releases |
| PlanetScale | Every database in the organizations the connection reaches, and each database’s branches |
| PostgreSQL | The one database the connection reaches |
| Railway | Services, databases and cron jobs in the chosen environment of each project the connection reads, the repositories they build from and the domains they serve |
| Render | Services, static sites, cron jobs, datastores and workflows, the repositories services and workflows build from and the domains they serve |
| Supabase | Every project the connection reaches, as a database, its preview branches and its Edge Functions |
| Tinybird | The workspace’s data sources and API endpoints, each endpoint linked to the data sources it reads |
| Trigger.dev | The tasks of the newest version deployed to the environment, as jobs |
| Turso | The databases the organization or group holds, and the branches made from them |
| Upstash | Redis databases, the QStash of each region, each workflow that ran recently and each active Box |
| Vercel | Projects, the repository each builds from and the verified domains it serves |
Some connections read more than one place, chosen when you connect: Northflank and Railway projects, Render workspaces, Vercel teams, Bitbucket workspaces, Azure DevOps projects, Google Cloud projects and Azure subscriptions. Pick one, several, or all the credential can read. Choosing all takes in one added later at the next read.
Firefight reads each connection every hour, and right after you connect or refresh one. GitHub, GitLab, Bitbucket, Azure DevOps and Cloudflare change slowly next to a deploy, so they are read once a day. People who can manage integrations can press Sync now at the top of the map to read every connection again straight away. Many connections also tell Firefight about a change as it happens, see Live updates.
A few things decide how complete the map is:
- Northflank jobs need the token’s role to have Project > Jobs > General > Read, workflows Project > Workflows > General > Read, and pipelines and their release flows Project > Pipelines > General > Read. Without one of them, the map lists everything else and says what could not be read and the permission to add.
- Cloudflare, ClickHouse, Neon, PlanetScale, Supabase, Turso and Upstash are read through the connection’s own tools, so the tools that list what it holds must be switched on for the connection under Integrations. For PlanetScale those are
planetscale_list_organizations,planetscale_list_databasesandplanetscale_list_branches, and Cloudflare needs execute. A tool that is off is named as the reason something is missing. - Neon Functions are read on each project’s default branch and its 24 most recently changed branches. An Upstash workflow shows while one of its runs is among its region’s latest 50, so a workflow that has not run lately leaves the map until it runs again.
Anything a connection could not read is listed under Not read in the panel beside the map, so a missing resource is known to be missing. The same list says when a connection’s last sync failed, or when its normal readings or usual log lines could not be read.
The three views
Section titled “The three views”- Map draws each account as a box, arranged in the direction things depend. A resource with an open incident is outlined in red, and one with no links is drawn fainter. The panel beside it lists what needs attention now, what changed in the last 24 hours (a deploy, a status that moved, a service that scaled, a setting that changed, something new or gone), what waits for your review, each connection’s live updates, and anything Not read.
- Focus shows one resource and everything one, two or three links away. Choose What it needs to follow what it depends on, What needs it to see what would stop if it failed, or Both ways. The panel beside it tells you everything about the resource, see A resource’s panel.
- Table lists every resource, ranked by how many others depend on it, with its links, the catalog entries it runs, its incidents over the last 30 days, its last change and any open incident. Only resources with no links shows what is not connected to anything yet.
Search, environment, provider and type filters narrow the Map and Table views. The view and the resource in focus are part of the page address, so you can share a link to exactly what you are looking at.
A resource’s panel
Section titled “A resource’s panel”Open a resource in Focus, or click it on the map, and the panel beside it reads top to bottom:
| Section | What it shows |
|---|---|
| What it is | Its kind, provider, account, environment and last status, details such as its plan, region or Instances, and Open in the provider |
| Runs, from the catalog | The catalog entries it runs, with what each is for and who owns it, as written in the catalog |
| Now | Its open incidents |
| Key checks | The first readings worth taking, see Key checks |
| Past incidents | Up to five incidents that ended on it in the last 180 days, each with one line on how it ended |
| Normal, over the last week | What each metric usually reads, the level 95% of readings stay under, and the peak |
| Usual log lines | The kinds of line it usually prints, see Usual log lines |
| Settings that point here | On a database, the settings of services that name it, see Which services use which databases |
| Links and how they were found | Each link, and Add link, see Links and how they were found |
| If it fails | What stops with it, and what else would stop if the suggested links are right |
| Halon remembers | What Halon has learned about it, shown when Halon is on for your workspace |
| What changed | Its recent changes, such as deploys, status moves, scaling and settings |
A past incident’s line comes from the completed postmortem’s summary first, then the incident’s summary. The running summary of the channel is used only when the incident is not private and your workspace lets people read transcripts. Now and Past incidents stay empty until a catalog entry is linked, since an incident names a catalog service, not a resource.
Normal is read once a day from a week of the provider’s own metrics, never estimated. When an observability tool you connect also watches the resource, its readings show beside the provider’s with its name, such as CPU (Datadog). A connection whose metrics could not be read says so under Not read.
Instances and scaling
Section titled “Instances and scaling”A service’s panel shows Instances, how many copies of it the integration runs or is set to run. When the count changes between one sync and the next, or when a live update says the service changed, the map records it as a scale, such as “web went from 2 to 6 instances”. It shows in what changed, Halon reads it as a change worth checking when something fails soon after, and it can start a Service scaled workflow.
| Integration | What counts |
|---|---|
| Northflank | The instances a service is set to run |
| Render | The instances a service runs, which autoscaling moves too |
| Railway | The replicas a service is set to run |
| Fly.io | An app’s Machines |
| Kubernetes | The replicas a deployment or stateful set wants, which an autoscaler moves too, and the pods a daemon set schedules |
| AWS | The tasks an ECS service is set to run, which service auto scaling moves too |
| Modal | The containers an app runs when the map reads it |
| DigitalOcean | The instances an app’s services and workers run |
| Google Cloud | The instances of a Cloud Run service set to manual scaling |
| Azure | The instances of an App Service or Function app’s plan, and the replicas of a Container App whose fewest and most are the same |
A service that scales on its own with no one number to read, such as a Cloud Run service on automatic scaling, a DigitalOcean app with an autoscaling component, an Azure Consumption or Elastic Premium plan, App Runner and Elastic Beanstalk, shows no count rather than a guess. Vercel, Netlify, Cloudflare, Convex and Trigger.dev run code on demand, and code hosts and databases run no copies of a service, so none of them has a count.
Links and how they were found
Section titled “Links and how they were found”A link reads as “this depends on that”, such as web runs builds of firefight, or app.example.com is served by web. Every link says how it was found.
| How it was found | What it means |
|---|---|
| Declared by the connection | The provider reports it, such as the build a service runs or the repository a build comes from. It goes away when the provider stops reporting it, so you cannot remove it by hand. |
| Matched from a setting | One of the service’s settings, such as DATABASE_URL, names the exact address the database’s own provider reports for it. It is a fact, drawn solid, and it lists the settings it came from. It goes away when the setting stops naming that address, so you cannot remove it by hand. |
| Added by a person | Someone added it with Add link because no provider reports it, such as a service that uses a database it reaches with a secret. |
| Suggested by Firefight | Firefight worked it out from clues, such as a service and a database named for the same project, a setting whose name points at a database’s provider, or a resource named in a repository’s infrastructure files, which suggests it is managed in that repository. It is drawn dashed until someone confirms it. |
| Suggested by Halon | Halon found it from evidence, such as connections to a database’s host in a service’s logs, and wrote down what it saw. It is drawn dashed until someone confirms it. |
The infrastructure files a code host is read for are files such as Terraform, Helm charts, Kubernetes manifests, Pulumi and CDK programs, and a platform’s own config, like wrangler.toml, fly.toml or vercel.json.
To add a link, open a resource in Focus and choose Add link under Links and how they were found. Pick what it depends on and how, and say how you know if you like. Remove link takes away a link someone added or a suggestion someone confirmed, after you confirm. On a link the provider reports or a setting names, Remove link stays inactive and its tooltip says why.
Suggestions appear under To review on the map and on the resource they start from, each with the clues behind it and how sure it is. Confirm link makes it part of the map. Dismiss removes it, and the same link is not suggested again.
A workflow or a pipeline’s release flow is linked to what it releases, such as web is released by shop Production, and a release flow is part of its pipeline. On AWS a pipeline is linked to the services, deployment groups, stacks and Elastic Beanstalk environments its deploy actions name, a CodeDeploy deployment group to the ECS services it deploys, and a CloudFormation stack to every resource it made. On Google Cloud each stage of a Cloud Deploy pipeline is linked to the Cloud Run services and jobs it released. A release failing stops nothing that is already running, so these links never count toward what stops if something fails.
Until you confirm a suggestion, it does not count toward what stops if something fails. The If it fails section in Focus lists the facts first, then what would also stop if the suggested links are right, and the table’s Depended on by column counts facts with suggestions shown beside them.
Adding, removing, confirming and dismissing links needs permission to change the catalog.
Which services use which databases
Section titled “Which services use which databases”A service says which database it uses in its settings, such as DATABASE_URL=postgres://app:...@ep-cool-river.eu-central-1.aws.neon.tech/app. On every sync Firefight reads each service’s settings where the connection allows it, and compares the address in each one with the addresses database providers report for their own databases. The value is never stored, shown, logged or handed to Halon, and neither is the password inside it. Firefight keeps only the setting’s name.
When a setting names the address of exactly one database, the service is linked to that database as a fact, with the setting’s name on the link. A database’s panel in Focus lists them under Settings that point here, such as DATABASE_URL from web.
Some matches are not certain, so they stay suggestions for you to confirm:
| How sure | When |
|---|---|
| Likely | A PlanetScale MySQL setting names PlanetScale’s shared host and a database of the same name, which another account could also have. Or the service and the database are named for the same project and the same environment, or for the same project with a setting whose name points at the database’s provider, such as NEON_DATABASE_URL. A service with no environment in its name, such as web, is taken as production. |
| Possible | They are named for the same project, but the database’s name says nothing about its environment. Or a setting’s name points at a provider or a kind of database, such as REDIS_URL, its value is hidden or names no address a provider reported, and only one database fits. Or two databases report the same address. |
A service and a database named for different environments, such as dev-web and firefight-prod, are never suggested. A likely link is drawn dashed and a possible one dotted, and both stay suggestions until you confirm them. A suggestion you dismiss is never made again, even if a setting later names that database.
Some providers hide a setting’s value, such as a secret on Fly.io, a sensitive variable on Vercel, a sealed variable on Railway or a Kubernetes Secret. Firefight never asks for those values, so such a setting counts only by its name.
Access that links more
Section titled “Access that links more”Every connection works with the access it already asks for. A few providers keep some settings behind extra access, which you can add if you want those services linked too. All of it is optional.
| Connection | What to add | What it links |
|---|---|---|
| Azure | A custom role on the apps holding only Microsoft.Web/sites/config/list/action | App Service and Function apps to the databases their app settings and connection strings name. Container Apps are linked without it. |
| Kubernetes | A rule letting the service account get configmaps in the connected namespaces | Workloads whose settings come from a ConfigMap. Secrets are never read. |
| Trigger.dev | An API key whose preset can read environment variables, instead of Observer | Tasks to what the environment’s variables name. Observer keeps the connection read only. |
Two connections ask for the access their settings need when you connect them. Each still works without it, and only these links are missing:
| Connection | What the connect form asks for | What is not linked without it |
|---|---|---|
| Northflank | Permission for the token’s role to read secret groups | Services and the databases linked to the secret groups they use. |
| AWS | ecs:DescribeTaskDefinition | ECS services and the databases their task definitions name. Lambda functions are still linked. |
Without any of this access, the map lists what it could not read under Not read, and everything else still links.
Linking the map to the catalog
Section titled “Linking the map to the catalog”In Focus, under Runs, from the catalog, choose Link a catalog entry to say which catalog entry a resource runs, such as linking the web service on Northflank to your Checkout service in the catalog.
Once they are linked, an incident that names that catalog service in its fields lights up the resource on the map, shows under Now in its panel, and counts toward its incidents over 30 days. Its panel shows what the service is for and who owns it, and how its incidents ended. A linked service, worker, job or function joins the daily read of usual log lines. Halon also reads the resource as where that service runs, and an investigation into an incident starts from the resources its services run on and what changed there before it began. Linking needs permission to change the catalog, and the x on an entry unlinks it after you confirm.
Live updates
Section titled “Live updates”Most connections tell Firefight when something changes, or keep a log of changes Firefight reads every few minutes, so the map follows a change long before the next scheduled read. When a change arrives, Firefight reads that resource again and updates what is different, such as its status, the commit it runs, its domains and the settings that link it to a database. A resource the provider no longer has leaves the map.
| Connection | How changes arrive | What brings an update |
|---|---|---|
| AWS | CloudTrail’s event history, read every 5 minutes in each region, and optionally a stack you create, see AWS | See AWS |
| Azure | The subscription’s activity log, read every 5 minutes, and optionally Event Grid, see Azure | Any change to an App Service or Function app, a Container App, an Azure SQL database, a PostgreSQL flexible server or a container registry, including one deleted |
| Azure DevOps | Service hooks Firefight adds | A push to a repository’s default branch, and a repository created, deleted or renamed |
| Bitbucket | A webhook Firefight adds | A repository created, imported, deleted, renamed or transferred, and a push to a repository’s main branch |
| CircleCI | Webhooks Firefight adds, one per project | A workflow or a job ending. These change nothing on the map, and let a watch hear at once |
| ClickHouse | Each service’s state and its ClickPipes’ states, read every 5 minutes | A service starting, stopping, idling or changing state, a service added or removed, and a ClickPipe added, removed, starting, pausing, stopping or failing |
| Cloudflare | Each account’s audit log, read every 5 minutes, and optionally a Pages notification you send, see Cloudflare Pages notifications | A change to a zone, its DNS records or settings, a Worker, a Pages project, an R2 bucket, a D1 database, a KV namespace, a queue, a Tunnel, a load balancer pool or a Hyperdrive configuration |
| Convex | A log stream Firefight adds once you turn it on, see Convex | Code pushed to the deployment, the deployment paused or unpaused, and a change to its settings |
| DigitalOcean | Each app’s events, read every 5 minutes | A deployment starting, moving to its next phase or ending, autoscaling changing how many instances a component runs, and an app deleted |
| Fly.io | Each app’s machines and newest release, read every 5 minutes | A machine starting, stopping or changing, a release starting, finishing or failing, and an app being created or deleted |
| GitHub | Firefight’s GitHub app | A repository created, deleted, archived, unarchived, renamed, moved or given another default branch, repositories added to or removed from Firefight’s GitHub app, and a push to the default branch that changes an infrastructure file |
| GitLab | A webhook Firefight adds | A push to the default branch that changes an infrastructure file, and a project created or deleted in the group Firefight follows |
| Google Cloud | The project’s audit log, read every 5 minutes | Any change to a Cloud Run service, Cloud SQL instance, Compute Engine instance or GKE cluster, including one created or deleted, and a Cloud Build build starting or ending, on the Cloud Run services its trigger deploys |
| Kubernetes | A watch on the cluster every 2 minutes | A deployment, statefulset, daemonset, cronjob, job, service or ingress in the connected namespaces being created, changed or deleted |
| Modal | The environment’s apps, read every 5 minutes | An app deployed, rolled back or stopped, and a new app deployed or one removed |
| Neon | Each project’s operations, read every 5 minutes | A compute starting, suspending or changing, and a branch being created, deleted, archived or restored |
| Netlify | Webhooks Firefight adds | A production deploy being published, and an earlier deploy being published again |
| Northflank | A webhook Firefight adds | A service deploying, building or scaling, a container crashing, being evicted or staying near its memory or CPU, a database backup starting or ending, a database’s disk filling up, a job run starting, ending or being stopped, and a release flow run starting, moving or ending |
| PlanetScale | A webhook Firefight adds to each database, or one you add, see PlanetScale | A branch becoming ready, going to sleep, starting maintenance or getting a new primary, and a deploy request moving through its steps |
| Railway | A webhook Firefight adds | A deployment changing status, such as building, deploying, deployed, failed, crashed, out of memory, sleeping, resumed, restarted or removed, and a CPU, memory or volume alert you set up in Railway firing or resolving |
| Render | A webhook Firefight adds | A build or deploy starting or ending, a service suspended, resumed or scaled, a cron job or one-off job running, an instance failing, a service’s instance type changing, a Postgres datastore created, becoming available or unavailable, restarting or upgrading, and a Key Value datastore becoming available or unhealthy or restarting for a new configuration |
| Supabase | An endpoint you create, see Supabase | A project created, paused, restored, restarted, removed, moved to another organization, changing status or starting a backup, and a preview branch created, updated or removed |
| Trigger.dev | Alerts you add, see Trigger.dev | A deployment succeeding |
| Vercel | A webhook Firefight adds | A production deployment starting, becoming ready, succeeding, failing or being canceled, a promotion or rollback, a rolling release starting, moving on, completing or being stopped, a project created, removed or renamed, an environment variable changing, and a domain added to a project, verified, changed, moved, removed or no longer verified |
A change sent by webhook reaches the map within about a minute. A change read from a log or a check takes a little longer:
| Connection | Reaches the map within about |
|---|---|
| Kubernetes | 3 minutes |
| ClickHouse, Cloudflare, DigitalOcean, Fly.io, Google Cloud, Modal, Neon | 6 minutes |
| AWS, from CloudTrail | 10 minutes, since CloudTrail itself takes around 5 minutes to record a change |
| Azure | 25 minutes from the activity log, since Azure adds a change to it 3 to 20 minutes after it happens, or about a minute with Event Grid turned on |
PostgreSQL, Tinybird, Turso and Upstash send no changes Firefight can follow, so they update at each hourly read.
What live updates do not follow
Section titled “What live updates do not follow”Some changes bring no update, and reach the map at the next scheduled read instead:
- Render sends nothing when a service is created or deleted, or when its settings change. A workflow’s task runs send nothing either, so a watch on one checks it every minute.
- Railway sends nothing when a service is created, renamed or deleted, or when its variables change.
- Northflank and Netlify send nothing when a service, database, job or site is added or removed, or when its settings change. Northflank sends nothing when a workflow or pipeline is added or removed, or when a workflow runs.
- PlanetScale sends nothing when a branch is resized or its settings change. A database added since gets Firefight’s webhook at the next hourly read.
- Azure DevOps sends nothing when a pipeline is added, renamed or removed, so pipelines change on the map at the daily read.
- CircleCI sends nothing when a project is added or removed, so a new project waits for the hourly read. A connection made through CircleCI’s own MCP server cannot add webhooks, so its live updates stay off and say so.
- ClickHouse changes to a service’s settings, or to where a ClickPipe reads from, wait for the hourly read.
- Convex sends nothing about what its functions print, which Halon reads when it needs it.
- DigitalOcean follows apps only. A Droplet or a database changing, and an app added, wait for the hourly read. A team with more than 100 apps is read 100 apps at a time, so a change there can take longer.
- Modal changes to how many containers an app runs wait for the hourly read.
- Trigger.dev follows only the alerts you send to Firefight, and only a deployment succeeding changes the map. A failed run, a failed deployment or an error group alert has Halon check its watches at once.
- Supabase sends nothing for an organization or project you did not create an endpoint for.
- Neon reaches only the projects already on the map, so a new project waits for the hourly read. A Neon Function’s new deployments wait for the hourly read too.
- Fly.io changes to an app’s certificates or Managed Postgres clusters wait for the hourly read.
- Kubernetes changes to a ConfigMap a workload reads, or to the labels a service picks a workload by, wait for the hourly read.
- Cloudflare keeps a renamed DNS record’s old hostname on the map until the daily read.
- GitLab sends nothing when a project is renamed, moved or given another default branch, and Bitbucket nothing when a repository is given another main branch. A change to a Pulumi or CDK program outside a folder named
infra,infrastructure,stacks,cdkorpulumibrings no update either. These wait for the daily read. - Bitbucket says a repository was deleted only once it is gone for good, which can take 30 days, so a deleted repository usually leaves the map at the daily read first.
Changes that touch nothing on the map bring no update at all, such as a preview deployment on Vercel, a deploy preview or branch deploy on Netlify, a push to a code host that changes no infrastructure file, or writing a value to a KV namespace, running a query on a D1 database or purging a cache on Cloudflare. While live updates are on, each connection’s details say what they do not follow.
Seeing whether they are on
Section titled “Seeing whether they are on”Each connection’s details under Integrations say whether live updates are on, and so does the Live updates section of the panel beside the map:
- Live updates: on, last event 3 minutes ago means changes reach the map as they happen.
- Live updates: on, no change received yet means Firefight is ready and has heard nothing so far.
- Live updates: off comes with the reason, such as the connection being switched off, the access it is missing, or the provider not letting Firefight add its webhook, quoting what the provider answered. The map still updates at each scheduled read.
When a provider turns Firefight’s webhook or its read down, Firefight tries again once a day, so live updates turn on by themselves once the provider allows it. For a webhook Firefight adds, people who can manage integrations can press Turn on to try again straight away. For a connection Firefight reads every few minutes, pressing Refresh tools on the connection under Integrations tries straight away.
The webhooks Firefight adds
Section titled “The webhooks Firefight adds”When you connect one of these, Firefight adds a webhook of its own with the connection’s access, and there is nothing for you to set up:
| Connection | Where the webhook goes | What it is called |
|---|---|---|
| Azure DevOps | Each project the connection reads, as service hooks under Service hooks in the project’s settings | - |
| Bitbucket | The workspace | Firefight live updates |
| CircleCI | Each project the token reaches | Firefight live updates |
| GitLab | The group every project the token reaches is in, or the one project it reaches | Firefight live updates |
| Netlify | Every site the token reaches, one for each event it follows | - |
| Northflank | Your team’s notification integrations, sending events from the connected project only | Firefight live updates followed by the project and a short code |
| PlanetScale | Each database on the map, see PlanetScale | - |
| Railway | The project, under Settings → Webhooks on Railway | - |
| Render | The workspace | Firefight live updates |
| Vercel | The team | - |
You can see it in the provider’s webhook settings. Firefight never changes or removes a webhook you made. Removing the connection in Firefight removes its webhooks, and adding and removing them appear in Activity under the Map sweep source.
A Netlify site you add later gets its webhooks within the hour, and Firefight turns a webhook back on if Netlify switched it off after deliveries failed. Railway’s webhook covers the whole project, pull request environments included, so a project connected once per environment has one webhook per environment, and each updates only its own environment on the map. A deployment in a pull request environment does not reach the map, and a watch Halon keeps on it checks again straight away. When Firefight starts following more events for Render, Railway, Netlify, Vercel or Azure DevOps, it updates the webhook it added at the next read, and there is nothing for you to do.
Adding the webhook needs some access on the provider’s side:
- Northflank needs the API token’s role to read, create and delete notification integrations (Account > Observability > Notifications).
- GitLab needs a token with the
apiscope. A group webhook needs the Owner role in the group and a group on GitLab Premium or Ultimate, and a project webhook needs the Maintainer role. A token that reaches projects in more than one group gets no live updates, so connect a group access token for each group instead. This works the same on your own GitLab. - Bitbucket needs a workspace owner’s token with the
read:webhook:bitbucket,write:webhook:bitbucketanddelete:webhook:bitbucketscopes. - Azure DevOps needs a token from a project administrator of each project, with Service Hooks (Read, query, & manage).
- CircleCI needs the token’s user to manage each project’s settings. When CircleCI lists more projects in an organization than Firefight reads at once, live updates stay off and say so.
GitHub needs no webhook. Firefight’s GitHub app sends updates for every repository you installed it on.
When Firefight asks first
Section titled “When Firefight asks first”A Render workspace may have room for only one webhook, and Render does not say how many a workspace is allowed. When a workspace has no webhooks yet, Firefight’s could be its only one, and the workspace could then not add one of its own. The same goes for a workspace one short of the most Render allows. In those cases Firefight does not add its webhook on its own. Firefight asks the same way for a Convex deployment, which can send to only one webhook log stream, and a PlanetScale database that already has four of the five webhooks PlanetScale allows. The connection shows Live updates: off with what adding it would mean, and a Turn on button.
Pressing Turn on shows that explanation again before anything changes. Confirm, and Firefight adds its webhook and says so. Once it is on, Turn off removes Firefight’s webhook again, which frees the room for one of your own, and Firefight does not add it back until someone turns live updates on. A Render workspace that already has a webhook of its own gets live updates without asking. Azure’s Event Grid is turned on the same way, see Azure. When the button cannot be used, it stays on the connection greyed out, and hovering it says why.
PlanetScale
Section titled “PlanetScale”When the connection reaches PlanetScale’s API, Firefight adds its own webhook to each database on the map, and to a database added later at the next hourly read. A connection reaches the API when you signed in to PlanetScale, or connected with a service token and its id, see Connect an integration. Each addition appears in Activity under the Map sweep source.
If one of your databases already has four of the five webhooks PlanetScale allows, Firefight’s would take the last one, so it does not add any on its own. The connection shows Live updates: off with which database that is and a Turn on button, see When Firefight asks first.
A connection made with a service token and no id cannot reach the API, so you add a webhook to each database you want followed. The connection’s details under Integrations show the address to send changes to, the steps, the events to select, and a Signing secret field. Until a secret is saved the connection shows Live updates: off and the map updates every hour.
- In PlanetScale, open a database, then Settings → Webhooks, and choose Add webhook.
- Paste the address from Firefight as the URL, and select the events listed in Firefight.
- Save the webhook, choose Show secret from its menu, paste the secret into Firefight and press Add secret.
- Do the same for each database you want followed.
Each database’s webhook has a secret of its own, so the field keeps every secret you add, and a change signed with any of them reaches the map. PlanetScale allows five webhooks per database, and Firefight’s takes one. Forget secrets removes all of them after you confirm, for example when you replace your webhooks. Changes then stop reaching the map until you add a secret again. PlanetScale sends deploy request events for Vitess databases only.
A deploy request moving has Halon check the watches reading through the connection at once, and one that applied its schema or stopped on an error starts any workflow whose trigger is Deploy or CI finished.
Supabase
Section titled “Supabase”Supabase also connects through its own MCP server, and sends changes through Platform Webhooks, which are in early access. Supabase turns away organizations outside its early access list, and their projects update every hour. The connection’s details under Integrations show the address, the steps and the event types to send.
- Choose a signing secret of 8 to 64 characters.
- With a Supabase personal access token, create an endpoint through Supabase’s Management API, with
POST https://api.supabase.com/v2/organizations/<organization slug>/webhooks/endpointsfor every project in an organization, or/v2/projects/<project ref>/webhooks/endpointsfor one project. - Give it the address from Firefight as its
url, your signing secret, and the event types listed in Firefight. - Do the same for each organization the connection reaches, with the same secret, then paste the secret into Signing secret in Firefight and press Save secret.
Saving a new secret for Supabase replaces the one before.
For both PlanetScale and Supabase, Firefight accepts a change only when it is signed with a secret you saved or one PlanetScale gave Firefight for its own webhook, and it never shows a saved secret again. Keep the tools that read a database and a branch on PlanetScale, or a project and its branches on Supabase, switched on for the connection. With them off, a change takes longer to reach the map.
Firefight reads the CloudTrail event history of every region an AWS connection reads, every 5 minutes. A change made in the AWS console, with the AWS CLI or by a deploy tool reaches the map within about ten minutes. The access key needs cloudtrail:LookupEvents, which the connect form asks for. Without it the connection shows Live updates: off with what AWS answered, and the map still updates every hour.
| Resource | What brings an update |
|---|---|
| ECS services | A service created, updated (a deploy, a new task count), deleted or tagged |
| Lambda functions | A function created, its code or configuration updated, a version published, an alias moved, deleted or tagged |
| EC2 instances | An instance launched, started, stopped, terminated, changed or tagged |
| RDS databases | A database created, restored, changed, rebooted, started, stopped, promoted, deleted or tagged |
| CodeBuild projects | A project created, updated or deleted |
| CodePipeline pipelines | A pipeline created, changed or deleted, and an execution started, stopped, retried or rolled back |
| CodeDeploy deployment groups | A group created, changed or deleted, and a deployment started |
| CloudFormation stacks | A stack created, updated, deleted, a change set run, and an update cancelled or continued |
| App Runner services | A service created, updated, deleted, paused or resumed, and a deployment started |
| Elastic Beanstalk environments | An environment created, updated, rebuilt or terminated, and its app server restarted |
An ECS deployment finishing is not in CloudTrail. In a region without the stack below, Firefight asks ECS about each service whose deployment started until it has finished, then reads the service again, so a deploy’s end reaches the map and a watch on it within about 10 minutes.
To get AWS’s changes as they happen, open the AWS connection’s details under Integrations and find Get changes instantly, which lists each region the connection reads. Choose Create stack beside a region. AWS’s CloudFormation console opens in that region with Firefight’s template, the connection’s address and its key already filled in. Tick the box that acknowledges the stack creates an IAM role, then choose Create stack.
The stack sends Firefight these, as they happen:
- EC2 instances changing state, ECS service events and deployments, and RDS database events
- CodeBuild builds and their phases starting and ending, so a watch on a build hears at once
- Pipeline executions, stages and actions changing state, CodeDeploy deployments changing state, App Runner operations and services changing status, and Elastic Beanstalk environments changing status or health
- Your other CloudFormation stacks changing status
- The changes in the table above, while the account has a CloudTrail trail that is logging
A stack created before CodeBuild projects, pipelines, deployments, stacks, App Runner and Elastic Beanstalk joined sends only what it was made with, and those changes keep arriving every 5 minutes. To have them sent as they happen too, delete that region’s firefight-live-updates- stack in CloudFormation. Once it is gone the region’s row offers Create stack again, and the new stack sends everything above. The same goes for a stack created before Lambda versions and aliases joined, which keeps sending those every 5 minutes until you create it again.
Lambda has no state changes of its own to send, so in an account without a trail, Lambda changes keep arriving every 5 minutes. Once a region sends its first change, its row says Sending with when Firefight last heard from it. Live updates stay on while either way works. If Firefight cannot read CloudTrail but a region sends changes, the reason says so and names the regions still sending.
A few regions do not offer what the stack needs: Melbourne, Taipei, Malaysia, New Zealand, Thailand, Calgary, Tel Aviv, Mexico and both AWS GovCloud (US) regions. Their rows say so, and their changes arrive every 5 minutes. In Beijing and Ningxia the stack is created in the China console, from Firefight’s template published in China. Until that template is published, their rows say so and their changes arrive every 5 minutes.
Firefight did not create the stack, so it cannot remove it. To stop, delete the stack in CloudFormation in each region you created it in. Its name, starting with firefight-live-updates-, is shown under Get changes instantly. Removing the AWS connection in Firefight stops accepting what the stack sends straight away, and the message that confirms it names the stack and the regions to delete it from.
Connections Firefight checks on a schedule
Section titled “Connections Firefight checks on a schedule”These send no updates Firefight can sign up for, so Firefight checks each of them on a schedule and reads again whatever changed. Firefight adds nothing to your account, and each needs a little access:
- Cloudflare reads the audit log through Cloudflare’s own server, with execute, so execute has to be switched on for the connection. Reading the audit log also needs the Account Settings Read permission. Without either, live updates are off with the reason, and Cloudflare is read once a day.
- Kubernetes needs the service account’s role to allow
watchon the same deployments, statefulsets, daemonsets, cronjobs, jobs, services and ingresses it can alreadygetandlist. Without it, live updates are off and the reason names what the role may not watch. Withwatchon events too, a Warning event about a workload, such as a pod failing to pull its image, reaches Halon’s watches on it. Without that, everything else still updates. - Fly.io needs nothing more. An organization with many apps takes longer to check, and in one with more than 240 apps a change can take longer than 6 minutes to reach the map.
- Neon needs the
list_operationstool switched on for the connection. If Neon’s server does not offer that tool, live updates are off with the reason, and Neon is read every hour. - ClickHouse needs the
get_organizationsandget_services_listtools switched on for the connection. ClickPipes are followed only whilelist_clickpipesis on. - DigitalOcean and Modal need nothing more. Firefight reads each DigitalOcean app’s events, and lists the Modal environment’s apps, every 5 minutes.
Every check through Cloudflare’s, Neon’s or ClickHouse’s server appears in Activity under the Map sweep source.
Cloudflare Pages notifications
Section titled “Cloudflare Pages notifications”A Pages build that starts from a push is not in Cloudflare’s audit log. To have Halon hear about Pages deployments as they happen, send Cloudflare’s Pages notification to Firefight. The Cloudflare connection’s details under Integrations show the address, the steps and a Signing secret field.
- Choose a long random secret, paste it into Signing secret in Firefight and press Save secret. Saving it first lets Cloudflare’s test reach Firefight.
- In the Cloudflare dashboard, go to Alerts, then Destinations, and under Webhooks choose Create.
- Paste the address from Firefight as the URL and the same secret as its Secret, then choose Save and Test.
- Go to Alerts, then Overview, and choose Create an Alert. Pick Pages, Project updates, choose the projects and the Deployment started, Deployment failed and Deployment success events, and add that webhook as its destination.
- Do the same for each Cloudflare account the connection reaches, with the same secret.
A Pages notification changes nothing on the map. It makes Halon check the deployments it is watching straight away.
Convex
Section titled “Convex”Firefight follows a Convex deployment through a log stream that sends Convex’s audit log to Firefight, and nothing else from the deployment. Convex lets a deployment send to one webhook log stream, and log streams are not on every Convex account. So Firefight does not add its own on its own. The connection shows Live updates: off with what adding it would mean, and a Turn on button, see When Firefight asks first. Adding and removing the log stream appear in Activity under the Map sweep source.
When the deployment already sends a webhook log stream of yours, Convex turns Firefight’s down, and the connection says so under Live updates: off. Firefight tries again once a day.
Trigger.dev
Section titled “Trigger.dev”Trigger.dev cannot add an alert through its API, so you add a webhook alert yourself. The connection’s details under Integrations show the address to send alerts to, the steps, and a Signing secret field. Until a secret is saved the connection shows Live updates: off and the map updates every hour.
- In Trigger.dev, open the project and environment the connection reads, then Alerts, and choose New alert.
- Choose Webhook, and paste the address from Firefight as its URL.
- Select Run fails, Deployment fails and Deployment succeeds, then save the alert.
- Copy the secret Trigger.dev shows for the webhook, paste it into Signing secret in Firefight and press Add secret.
- To hear of error groups too, open Errors, choose Configure alerts, add a webhook with the same address, and add its secret in Firefight the same way.
Each alert has a secret of its own, so the field keeps every secret you add, and an alert signed with any of them is accepted. A deployment that succeeds updates the environment’s tasks on the map. A deployment that succeeds or fails also starts any workflow whose trigger is Deploy or CI finished. Forget secrets removes all of them after you confirm.
Firefight reads the activity log of every subscription an Azure connection reads, every 5 minutes, with the access the connection already has. A change reaches the map within about 25 minutes, since Azure adds a change to its activity log 3 to 20 minutes after it happens.
To get Azure’s changes as they happen, open the Azure connection’s details under Integrations and choose Turn on under live updates. Firefight then subscribes the connection to each subscription’s resource changes through Azure Event Grid, and Azure makes an Event Grid system topic in the subscription to send them. A change then reaches the map within about a minute, and a watch on it hears at once. The activity log is still read every 5 minutes, so a change Event Grid misses still arrives.
Event Grid needs two things the connection was not asked for:
- The service principal needs the EventGrid EventSubscription Contributor role on each subscription it reads.
- Microsoft.EventGrid must be registered as a resource provider on each subscription. In the Azure portal, open the subscription, then Resource providers, and register it.
Pressing Turn on says this again before anything changes. When something is missing, Firefight names the subscription and what it lacks, and the activity log keeps working. Give the access, then press Turn on again. A subscription the connection reads later is subscribed at the next hourly read, with the same access.
Turn off removes Firefight’s Event Grid subscription, and Azure removes the system topic it made for it. The activity log is still read every 5 minutes, so the connection still shows live updates as on. Adding and removing the subscription appear in Activity under the Map sweep source.
Key checks
Section titled “Key checks”Key checks are the first readings worth taking on a resource, such as a service’s error rate and p95 latency. Open a resource in Focus to see its checks under Key checks, each with the connection it reads from and what is normal for it over the last week, such as “usually 80 ms, 95% under 133 ms”.
| Kind | Key checks |
|---|---|
| Service | Error rate, p95 latency, CPU, memory, recent deploys |
| Worker | Error rate, CPU, memory, recent deploys |
| Job | How it stands, errors, CPU, memory, recent deploys |
| Function | Invocations, errors, duration, throttles |
| Database | CPU, memory, connections, disk |
| Database branch | How it stands, CPU, memory, connections, disk |
| Virtual machine | How it stands, CPU, memory, disk |
| Compute | How it stands, CPU, memory |
| Cluster | How it stands |
| Domain | Availability |
| Static site | Availability, recent deploys |
| Zone | Availability, traffic, error rate |
| Repository | CI status, recent deploys |
| Queue | Recent errors |
Buckets, key value stores, database proxies, tunnels, load balancers, origin pools, access policies and build services have no key checks, and their panel says why. Error rate reads 5xx responses, or errors where a provider counts no responses, and the check says which it reads.
Choose Run to take the reading now. The answer appears under the check with its chart and a line saying how it compares with normal, such as “Now 412 ms, 3.1x the usual high of 133 ms”. A check runs as you, through the connection’s own tool, so it needs the same permission, waits for the same approval rules and shows in Activity under that tool. Without the permission, Run stays visible but inactive, and its tooltip names what to ask an admin for. When a call needs approval, the check says so, and you run it again once someone approves it.
A check that cannot run here says why, such as the connection’s tool being switched off under Integrations, or the provider not keeping that reading for the resource. Switching the tool on brings the check back straight away.
Usual log lines
Section titled “Usual log lines”Firefight learns the kinds of line each important resource usually logs, so a line seen during an incident can be told apart from one that was there all week. Open a resource in Focus to see the ten it prints most under Usual log lines, each with how many lines followed it in the last read and how many daily reads saw it. Error and warning lines are marked.
Once a day Firefight reads a sample of logs from across the last week. It reads these resources, up to 200 a connection each day:
- Services, workers, jobs and functions linked to a catalog entry
- Resources whose catalog services had an incident in the last 90 days
- The 50 resources most others depend on
Before anything is kept, Firefight removes anything that looks like a credential, then replaces times, numbers, ids, email addresses, IP addresses, query strings and quoted values with placeholders, such as GET /orders/<NUM> <NUM> in <NUM> ms. Only these patterns are kept, never the lines, and a pattern no read has seen for a week is dropped. The reads use the connection’s logs tool, which must be switched on under Integrations, and appear in Activity under the Map sweep source.
A resource with no usual log lines says why, such as its logs tool being switched off, it not being among the resources Firefight reads, or it not being read yet. Linking it to the catalog entry it runs brings a service into the daily read.
Searching
Section titled “Searching”Press Ctrl K, or ⌘K on a Mac, on any dashboard page, or choose Search at the top of the page, to search the map, the catalog and what Halon remembers in one place. On the chat page the shortcut searches your chats instead, so use the Search button there.
Type any of these:
- A name or a provider’s id, such as
payments-dbor an AWS ARN. An exact match always comes first. - Part of a name, or one with a typo, such as
paymorledgr. - A tag, such as
team=payments, or either half of it. - A team, to find what it owns, or a catalog service, to find what it runs on.
- What a service does, such as
sends receipts. A catalog entry with a description is found by what its description means, not only by its words, when Halon is turned on for your workspace.
Results from the map, the catalog and confirmed memories are ranked together, best first. Each says where it lives, such as a database on Northflank in Production, and why it matched, such as its name or a team that owns it. The best 25 are shown, so add a word to narrow a long list.
Choosing a result opens it:
| Result | Opens |
|---|---|
| A resource | The map in Focus on that resource |
| A catalog entry | Its catalog type, with the entry open |
| A memory | The Memory page, with that memory marked |
Searching needs permission to read the map, and only shows what you can see. Approval rules never hold a search, since it only reads. Resources come from the environments you can read on the map, catalog entries need permission to read the catalog, and memories need Halon to be turned on and permission to read memory. Only memories someone confirmed are searched.
Who can see the map
Section titled “Who can see the map”Reading the map is its own permission, Resource Map. Members see the whole map in every environment without a grant, and admins and owners always do. An admin can limit a member to some environments by granting them Resource Map scoped to those environments, and from then on the map, the search and the map tools show them only what runs there. The map then says which environments it is showing, and that an admin decides which ones you see. Agents and service keys read the map only once they are granted Resource Map. See Permissions for how to grant it.
What you can do on the map follows your other permissions. Sync now needs permission to manage integrations, and adding, removing, confirming or dismissing links and linking catalog entries need permission to change the catalog.
Halon and agents
Section titled “Halon and agents”Halon reads and searches the map when you ask it about your infrastructure, so it knows what runs where without listing each provider again, and it can suggest a link it finds evidence for. Agents you connect over the MCP server have the same tools:
| Tool | What it does |
|---|---|
get_resource_map | The whole map one line per resource, or one resource’s fact sheet with its links within two hops, its key checks and the log lines it usually prints |
search_map | One search across the map, the catalog and confirmed memories, the same as the dashboard’s search |
find_resources | Resources by provider, kind, account, environment, status, owning team, catalog service or recent change, a page at a time |
get_resource | One resource’s details, its catalog services, its normal readings and key checks, and how many links lead in and out |
get_resource_links | The links into and out of one resource, each with how it was found |
get_resource_neighbours | The resources one link away, both ways |
traverse_resource_map | A walk from one resource toward what it depends on or what depends on it, up to several links away |
blast_radius | What fails with a resource, counted by kind, provider and environment, with the catalog services and open incidents it reaches |
resource_map_stats | The map in numbers, with each connection’s last read and what it could not read |
suggest_resource_link | Suggests a link between two resources with the evidence for it. It shows under To review until someone confirms or dismisses it |
run_key_query | Runs one of a resource’s key checks and says how the reading compares with normal |
new_log_patterns | Reads a resource’s recent logs and answers which kinds of line it did not print in the last week, and which of its error lines are usual |
Each link the tools read names the settings it came from, never their values. Only what runs in the environments the caller may read is found or counted. Suggesting a link needs permission to change the catalog, and run_key_query and new_log_patterns need the same permission as the connection’s own tool and show in Activity under it. Halon does not blame a log line the resource printed all week unless something shows it changed, such as a new pattern, a reading above normal or a deploy.