Skip to content

Instantly share code, notes, and snippets.

@aaronschachter
Last active May 27, 2026 07:09
Show Gist options
  • Select an option

  • Save aaronschachter/097d9b166fdba9620f63ae7e0146bc68 to your computer and use it in GitHub Desktop.

Select an option

Save aaronschachter/097d9b166fdba9620f63ae7e0146bc68 to your computer and use it in GitHub Desktop.
One-pager: Stale branch domain pruning to reduce SIP latency

Stale Branch Domain Pruning

Problem

Sites with many published branch staging domains accumulate distinct live publications. During Single Item Publish (SIP), writeToAllLive fans out CMS writes to every distinct lastPublicationId across all domains, including branch domains. This scales linearly with the number of distinct publications.

Example: Synthesia (enterprise, localized, custom staging domain) has 8 live publications, including several from branch domains published in April/early May that were never merged or deleted. SIP traces show 43-46s durations, with users experiencing spinning publish buttons, 504 timeouts, and items stuck in "Changes in Draft."

Why this happens

  • When a branch is published, branch.markPublished() stamps the current publication ID into branch.domain.lastPublicationId.
  • Branch publishes reuse the latest existing publication (they don't create new ones, per PR #61887 / ENT-2030), but the publication ID is frozen at publish time.
  • Main site publishes do NOT update branch domain publication IDs. This is intentional: branches represent a point-in-time snapshot, and auto-updating could surface content the branch author didn't intend.
  • Merged branches clean up after themselves (deleteBranch calls site.unpublish on the staging domain).
  • Branches that are published but never merged or deleted persist indefinitely, each holding a distinct publication ID.

Impact

Every stale branch domain with a unique lastPublicationId adds:

  • One additional database write per SIP operation (via writeToAllLive)
  • One additional entry protected from publication pruning (via schedulePublicationPrunes)
  • Additional latency on the /primary?live=true endpoint for localized sites (writes propagate across all locales per publication)

For sites with localization and/or custom staging domains, this compounds quickly.

Proposed solution

A background job that identifies and unpublishes stale branch staging domains, paired with UI visibility so users aren't surprised.

Backend

  • New scheduled job: query branches where domain.lastPublished exceeds a threshold (e.g. 60 days) and the branch has no recent activity (no commits, no merges in progress).
  • "Unpublish" means nulling out domain.lastPublicationId and calling site.unpublish({unpublishTarget: branch.domain.name}) to tear down CDN assets. The branch itself is NOT deleted.
  • Republishing the branch restores the staging domain with a fresh publication ID.

Frontend

  • Indicator in the Designer branches panel that a branch's staging domain was auto-unpublished due to inactivity.
  • One-click republish action to restore the staging URL.
  • Optionally: warning before auto-unpublish (e.g. email or in-app notification to the branch creator).

Open questions

  • What's the right inactivity threshold? 30 days? 60 days? Should it be configurable per workspace?
  • Should we notify the branch creator before unpublishing, or just show the state after the fact?
  • Are there enterprise customers who intentionally keep long-lived branch staging domains for review workflows?

References

  • Synthesia SIP investigation: #triage-cmsext thread
  • PR #61887 (ENT-2030): "Don't publish new publication when publishing to a branch domain"
  • Key files:
    • entrypoints/server/models/branch.ts (markPublished)
    • packages/domains/custom-domains/server/src/custom-domain.service.ts (getDomainsByLivePublicationIdMap)
    • entrypoints/server/lib/logic/cms/internal/items/writeToAllLive.ts
    • packages/domains/change-coordination/branches/server/src/branch.repository.ts (findDomainsBySiteId)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment