Give every pull request its own isolated Neon database branch
When a pull request opens, we create a private copy of your production database just for that review, then delete it the moment the pull request closes.
Build me a code workflow that gives every GitHub pull request its own isolated Neon Postgres branch, so reviewers can test against production-shaped data without ever touching production. Trigger it with a GitHub webhook on pull request events, and route on the event action: "opened" provisions the database branch, "closed" tears it down.
When the action is opened, call Neon's Create branch on my project with the production branch as the parent, so the new branch starts from a copy of real data, and attach a read-write compute endpoint so the branch is immediately connectable. If the compute is not created as part of that same call, follow it with Create compute endpoint for the new branch. Name the branch strictly pr-<number>, using the pull request number from the webhook payload, lowercase and with no other decoration.
Neon's mutating calls are asynchronous. Create branch and Create compute endpoint return an operations array, and the work is not finished when the call returns. Before doing anything that depends on the branch existing, poll Retrieve operation details for each returned operation id until its status is finished. Back off between polls, and fail with a clear message if an operation reports a failed or errored status rather than continuing.
Once every operation reports finished, and only then, use GitHub's Create an Issue Comment on the pull request number to confirm the database branch is ready. The comment should name the branch (pr-<number>) and link to the Neon console so developers can open the branch and pull credentials themselves. Critically, never put the Postgres connection string, the role password, or any other live credential into that comment: it is visible to everyone with access to the repository. Do not call the connection URI or reveal password operations anywhere in this workflow, and never write credentials into logs or saved output.
When the pull request event action is closed, which covers both merged and closed without merging, tear the branch down. Resolve the branch by name using List branches with a search for pr-<number>, take the id of the matching branch, and call Delete branch on it. Deleting the branch also idles and removes its compute, so no separate compute cleanup is needed. If no branch matches that name, treat it as already cleaned up and finish quietly instead of failing the run.
Use Get a Pull Request when the workflow needs to confirm the pull request's current state before acting, for example on a replayed or out-of-order webhook delivery. Keep the naming convention strict in both directions: provisioning always writes pr-<number> and teardown always looks up exactly pr-<number>, so the two halves can never drift apart. If a branch named pr-<number> already exists when a pull request is reopened, reuse it rather than creating a duplicate.
What does this prompt do?
- Every time someone opens a pull request, we create a private copy of your production database reserved for that review.
- Reviewers test against realistic data that is completely separated from the live database, so nothing they try can reach real customers.
- As soon as the copy is ready, we post a comment on the pull request pointing the team to it.
- When the pull request is merged or closed, we delete the copy automatically so you are not paying for databases nobody is using.
What do I need to use this?
- A Neon account containing the database you want copies made from.
- A GitHub account with access to the repository you want this to watch.
- Permission to add an automation to that repository so we can see when pull requests open and close.
How can I customize it?
- Choose which database the copies are branched from, such as production or an already masked staging database.
- Change the naming pattern for the copies if your team already has its own convention.
- Decide whether a copy is removed the instant a pull request closes or kept for a short grace period first.
FAQs
Will reviewers be looking at my real production data?
Is the database password posted in the pull request comment?
What happens if a pull request is closed without being merged?
Could this leave stray databases behind?
Does this add to my Neon bill?
Related templates
When you merge a fix in GitHub, this agent checks the matching dead-letter queue, replays the failed messages, and reports back on the pull request and in Slack.
Every night, find the preview databases whose pull request closed days ago, delete only the ones that are safe, and report the savings in Slack.
Every weekday morning, surface the security checks nobody has reviewed yet, file them in the right repository, and post your team one clear summary.
When a pull request changes the database, we create a matching PlanetScale branch for reviewers and post its name right on the pull request.
The moment a Render deploy fails, get a Slack post naming the likely cause, the commit and author behind it, and the last deploy that worked.
Every month, turn the features that truly reached customers into a plain language release note draft in Notion, ready for a product manager to review.
Stop sharing one staging database across every pull request.
Give each review its own isolated copy of real data, and have it cleaned up automatically the moment the pull request closes.