Clean up stale PlanetScale branches before they cost you money
Every morning, find the development branches nobody is using anymore, skip anything with a migration still in flight, delete the rest, and post a Slack recap.
Every day at 7am, clean up development branch sprawl across our PlanetScale databases before it quietly costs us money. Build this as a deterministic code workflow on a cron trigger. Every step is a known operation, so no agent reasoning is needed.
Expose these as configurable inputs with sensible defaults: the PlanetScale organization name, the age threshold in days (default 14), a list of protected branch names that must never be deleted (default should include staging), and the Slack channel that receives the summary.
Step one, use PlanetScale List databases to get every database in the configured organization. For each database, use PlanetScale List branches to get its branches. Both of these endpoints are paginated, so page through until there are no more results rather than reading only the first page.
Step two, select the deletion candidates. From each database's branches, drop the production branch, identified by the branch's production flag rather than by guessing at its name. Drop any branch whose name appears in the configured protected list. From what remains, keep only branches whose created_at timestamp is older than the age threshold, comparing against the current time in UTC.
Step three, protect in flight migrations. For each database, use PlanetScale List deploy requests and collect the branch names attached to any deploy request that is still open. Remove those branches from the candidate list. This rule matters more than the cleanup itself, so an unfinished migration is never destroyed, and if the deploy request lookup fails for a database, skip that database's deletions entirely rather than deleting without the safety check.
Step four, use PlanetScale Delete a branch on each remaining candidate. If an individual delete fails, do not abort the whole run. Record the failure and carry on to the next branch, then include the failures in the summary.
Step five, post exactly one Slack message to the configured channel using the Slack Bot Send a Message operation. Group the results by database, listing the branch names that were deleted along with their age in days, and the count of branches remaining on that database afterwards. Add a short trailing line covering what was intentionally skipped and why, separating branches held back for an open deploy request from ones excluded as protected or production. Post the message even when nothing was deleted, stating that the check ran and found nothing old enough, so that a silent failure never looks the same as a clean result. Format the message with Slack mrkdwn, using single asterisks for bold.
Example output
What does this prompt do?
- Checks every one of your PlanetScale databases each morning and finds development branches older than a cutoff you choose, 14 days by default.
- Leaves your production branch alone, plus any branch you add to a protected list, so long lived staging branches are never touched.
- Skips any branch that still has an open deploy request, so a migration that is mid flight is never destroyed.
- Deletes what is left and posts a single Slack message showing what was removed from each database and how many branches remain.
What do I need to use this?
- A PlanetScale account, with permission to view and delete branches on the databases you want cleaned up
- The name of the PlanetScale organization that holds those databases
- A Slack workspace and the channel where the daily summary should land
How can I customize it?
- Change the age cutoff. Fourteen days is the default, but teams that move faster often drop it to seven.
- Add branch names to the protected list so long lived staging or demo branches are always skipped.
- Move the run time or the destination channel, or switch it to weekly if daily feels noisy.
FAQs
Could this delete our production branch by accident?
What happens if someone is in the middle of a migration?
Why does leaving old branches around cost money?
Does PlanetScale not already clean up branches on its own?
What does the Slack message look like if nothing needed deleting?
Related templates
When someone leaves, we check which shared passwords they used in their final months and post a ranked rotation list to your security channel.
Every Monday, check every S3 bucket for public exposure, missing encryption and weak backup settings, then get the risks ranked in Slack.
Twice every weekday, the conversations from your social inbox land on the right HubSpot contact timelines, with a Slack recap for sales.
Every morning, find the addresses that hard bounced or filed a spam complaint, update the matching HubSpot contacts, and post a short Slack recap.
Every weekday at 4pm, spot the threads that went quiet, stage a ready-to-send nudge in your mailbox, and get a ranked Slack recap.
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.
Stop paying for branches nobody remembers creating.
Set the cutoff once and let the cleanup run every morning, with a Slack recap so the team always knows what was removed.