Build1 distinct publisher3 min readUpdated
A team's CI backup job allowlisted its runner IP on DigitalOcean managed Postgres. The database switched from credentials-only to allowlist-only, and production fell off the list it was never on.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A team added a database backup pipeline that temporarily allowlists the CI runner's IP, runs `pg_dump`, then revokes the IP, which is the standard pattern for CI-driven database jobs [3]. The first run did all three steps correctly and took production down while doing it [4][6].
The setup before the pipeline is the part worth reading twice. Their DigitalOcean managed Postgres had no trusted-source rules at all, which in practice means open to anything holding the connection string and credentials [1]. The application droplet reached the database over a public IP and had never needed an allowlist entry [2]. Then the pipeline ran one command, `doctl databases firewalls add` with the runner's IP [4].
According to the team's account, DigitalOcean flipped the database into enforcement mode the moment that single rule existed [5]. The runner was on the list. The droplet was not, because there had never been a list [6]. The dump succeeded and the application returned 500s for every request for the duration of the window [7]. Traffic was dropped at the network layer, not the auth layer, so from the application's side the database had simply vanished [11].
The semantics are documented, after a fashion. The team eventually found a docs page saying trusted sources are enforced "when configured," where "configured" turns out to mean "any rule exists" [8]. There is no dashboard warning and no confirmation prompt at the transition [9]. That is the whole trap: a zero-to-one rule change is a security-model cutover, while every one-to-many change after it is merely additive [17]. The command looks identical in both cases.
Recovery is cheap once you know. Removing all rules returns the database to open mode [10], and adding the production droplet's IP permanently means later runner entries are just extra rows in an existing allowlist with no enforcement flip [12]. The team also switched from `add` to `append`, which has the same effect for a single rule but makes explicit that you are not overwriting the whole firewall [13].
The durable fix is a preflight, not a runbook note. Their workflows now resolve the production droplet's public IP, check it against `doctl databases firewalls list`, and exit non-zero with the exact `append` command if it is missing, so an operator has to add the rule once, deliberately, before any workflow can open a runner IP [14]. The same guard went into the backup, seed and restore workflows, everywhere trusted sources get mutated [15].
Worth checking on your own estate: whether any managed database is currently running with an empty trusted-source list, because that is the configuration where an innocuous-looking firewall call becomes an outage. This is one team's report, published on dev.to and originally on their own blog [16], so treat the exact enforcement behaviour as something to verify on a staging database before you rely on it either way.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
DigitalOcean flipped the database into enforcement mode the moment a single rule was added, moving it from 'anyone with credentials' to 'only IPs on the allowlist'.
The team eventually found a docs page stating that trusted sources are enforced 'when configured'; in practice 'configured' means any rule exists, and adding the first rule is the moment enforcement changes from off to on.
The team's DigitalOcean managed Postgres had no trusted-source rules at all, which by default means open to anything that has the connection string and credentials.
The droplet running their application talked to the database from a public IP, with no allowlist entry required.
Their backup pipeline temporarily allowlists the runner IP, runs pg_dump, then revokes the IP; the author describes this as the standard pattern used by basically every CI-driven DB job.
The new pipeline added one rule with the command: doctl databases firewalls add "$DB_ID" --rule "ip_addr:${RUNNER_IP}".
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Concrete but single-sourced first-hand account
The account is specific and reproducible-looking: exact doctl commands, the awk parsing pitfall, and a complete preflight workflow step. But every claim traces to one self-reported post by the affected team, with no vendor documentation excerpt, no DigitalOcean response, and no independent reproduction of the enforcement-flip behavior in the cluster.
One disclosed deployment and fix
The only adoption evidence is a single team's disclosure that it hit this on a live DigitalOcean managed Postgres cluster and then replicated a preflight guard across its backup, seed and restore workflows. Nothing indicates how widely the platform behavior or the guard pattern is encountered elsewhere.
Mildly overstated generalization
The framing ('DigitalOcean Postgres Has a Firewall Trap') generalizes one team's unverified experience into a platform defect, and the surprise partly stems from having run a production database open to anyone with credentials, a risk the post does not dwell on. The mechanics described are internally consistent and the remediation is understated rather than hyped, so the gap is modest rather than severe.
Practitioner self-publication, low commercial pressure
This is an author-published incident write-up on dev.to, cross-posted from the author's own blog, with no disclosed vendor relationship, sponsorship, or product being sold. The visible incentive is attention and reputation for a dramatic postmortem, which favors sharp vendor-fault framing but not fabricated technical detail.
Plausible mechanics, unverified generalization
Confidence is moderate: the incident narrative and remediation are detailed and self-consistent, and the failure mode (network-layer drops once an allowlist becomes non-empty) is mechanically plausible. It is capped by the absence of any second source, vendor confirmation, timing/impact figures, or evidence that other operators have hit the same cutover.
build
Your "Index Only Scan" Did 2,847 Heap Fetches: Covering Indexes Are a Vacuum Problem1 distinct publisher
build
The optional EntityManager is the bug: moving the transaction boundary into AsyncLocalStorage1 distinct publisher
build
Three attackers hide behind one connect button, and encryption only stops one of them1 distinct publisher
build
A cleanup commit deleted the sanitizer. Five days later a scanner cashed it in.1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 18, 2026