Netlify#
The Netlify module ingests a Netlify team and everything it owns: sites and their published deploy, functions, dev servers, agent runners, Netlify DB branches and snapshots, environment variables, build and notification hooks, deploy keys, snippets, add-on service instances, DNS zones and records, TLS certificates and forms. See configuration for token and team setup, and the generated schema for every node, property and relationship.
Tenancy#
Netlify has a single tenancy level. A team (NetlifyAccount) owns everything, and every node in
this module is scoped to that team for cleanup, including the ones that also hang off a site. One
Cartography run syncs one team, so --netlify-account-slug is required.
Users are the exception to that ownership. A Netlify user is a shared identity that can belong to
several teams, so the node is never deleted by a team’s cleanup and both of its team edges are
scoped to the team being synced. Ask who is on a team by traversing MEMBER_OF, not by node
existence. An address invited to a team that has not accepted yet has no Netlify user behind it,
so it becomes a NetlifyInvite keyed on the email instead.
Secrets that are deliberately not ingested#
Several Netlify endpoints return live credentials in plain text. Cartography drops them and records only whether one is configured:
Field |
Handling |
|---|---|
|
Dropped. Netlify masks a secret value to its last four characters and returns a non-secret value in full; neither is stored. Only the key, scopes and deploy contexts are. |
|
Dropped. Cartography never calls |
|
Dropped. Anyone holding it can trigger a production deploy. |
|
Dropped. Holds the Slack incoming-webhook URL, target webhook URL or git provider token, depending on hook type. |
|
Dropped, replaced by |
|
Never returned by the API; |
|
Dropped. |
|
Dropped. Hold the credentials an add-on provisioned. |
What is not ingested#
Deploy history. Only the deploy currently published on each site. The full history is an append-only list that can hold thousands of entries per site.
Agent runner sessions. A session is a live execution record (prompt, step list, result diff) rather than inventory. The runner itself is ingested.
Form submissions. The form is ingested with its field names and submission count; the submitted data is personal data and is left alone.
Audit log. Retention is plan-gated and the volume is unbounded.
Rate limits#
Netlify allows 500 requests per minute and reports the remaining budget in
X-RateLimit-Remaining. A 429 comes with Retry-After, which the session’s retry policy
honours, so no explicit throttling is needed. Cartography logs a warning when fewer than 25
requests remain in the current window.
The budget for a team with S sites is roughly:
Call |
Requests |
|---|---|
List accounts (resolve the slug) |
1 |
List members |
1 |
List sites |
ceil(S / 100) |
Team-wide environment variables |
1 |
Deploy keys |
1 |
Per site: functions, dev servers, agent runners, environment variables, build hooks, notification hooks, snippets, service instances, TLS certificate, forms |
10 |
Per site with a Netlify DB: branches, snapshots |
2 |
DNS zones, plus one call per zone |
1 + Z |
That is about 10S + Z + 5 requests per sync, so the limit supports roughly 45 sites per
minute. Deploys cost nothing: the published deploy is embedded in the site payload.
Cartography always pages a list endpoint to the end. Handing a truncated result to the cleanup
jobs would make them delete every resource past the last page read, so a page that advertises a
successor it cannot reach raises NetlifyPaginationError instead of returning a short list.