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."
- When a branch is published,
branch.markPublished()stamps the current publication ID intobranch.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 (
deleteBranchcallssite.unpublishon the staging domain). - Branches that are published but never merged or deleted persist indefinitely, each holding a distinct publication ID.
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=trueendpoint for localized sites (writes propagate across all locales per publication)
For sites with localization and/or custom staging domains, this compounds quickly.
A background job that identifies and unpublishes stale branch staging domains, paired with UI visibility so users aren't surprised.
- New scheduled job: query branches where
domain.lastPublishedexceeds a threshold (e.g. 60 days) and the branch has no recent activity (no commits, no merges in progress). - "Unpublish" means nulling out
domain.lastPublicationIdand callingsite.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.
- 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).
- 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?
- 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.tspackages/domains/change-coordination/branches/server/src/branch.repository.ts(findDomainsBySiteId)