Deployment previews
A YoFix preview is a fully-functioning, publicly-reachable deployment of the application at a specific commit. Every push to a branch under an open PR produces one.
The lifecycle
- Webhook: GitHub fires a
pull_requestorpushevent. - Enqueue: the API atomically claims the event, creates a
Deploymentrow in the database, and enqueues a build job on thedeployBullMQ queue. - Build: a deploy worker (any one of the pool) claims the job, clones the repo at the exact commit, installs dependencies, runs the detected build command, and uploads the resulting artifacts to your configured storage provider (R2 by default).
- Manifest: once the artifacts are uploaded, the worker writes a manifest mapping the preview hostname to the artifact prefix.
- Serve: the preview server reads the manifest, fetches
artifacts from storage (with NVMe disk cache for hot files), and
serves them under
your-branch.yofix.dev(or your custom domain). - Comment: the API posts (or updates in place) the PR comment with the preview URL and build status.
Every step publishes progress over Redis pub/sub, which the dashboard streams to your browser over WebSocket. You see the build in real time.
Idempotency
Pushing the same commit twice produces the same artifact. Re-running the
same job (e.g. on retry) does not double-build, double-upload, or
double-post the PR comment. PR comments are keyed by an HTML marker
<!-- yofix-deploy:projectId={id} --> so we always find and update the
existing comment instead of creating a new one.
Atomic claiming
The deploy queue uses BullMQ’s atomic job-claiming primitive on Redis. Even when multiple worker nodes run in parallel, a job is claimed by exactly one worker. There is no double-write risk and no need for distributed locks at the application layer.
Caching
Build dependencies are cached on the worker’s NVMe disk per-project and per-lockfile-hash. A re-run of the same commit on the same project with no lockfile change typically completes in seconds. Preview artifacts themselves are deduplicated by content hash before upload.
Retention
Previews and their screenshots are kept for 14 days after they go ready, then removed. The latest preview on each open pull request is always kept, so a PR under review never loses its link. Replaced production deployments are kept for 120 days after a newer build takes over; your live production deployment is always kept. Both windows can be changed per project in Project settings → Build; the options above your plan’s cap are locked.
Visual test screenshots follow the preview window: a run keeps its results, but its images are removed once the project’s preview retention has passed. Screenshots of the latest preview on an open pull request are kept with it. Reviewing an expired change again takes a re-run.
A deployment whose files were removed shows as Expired. It is not a
failure: the build succeeded and its history stays in the activity feed.
Pick Redeploy to build the same commit again. A preview rebuild takes
its branch URL again. A production rebuild replaces the live site, unless
a newer build already holds production, in which case it gets its own URL
until you make it live with Rollback. Deployments uploaded with
yofix deploy have no repository to rebuild from, so run yofix deploy
again instead.
Build caches are removed 14 days after they were last used, and a branch’s cache is dropped when its pull request closes. The cleanup job runs daily and is idempotent.