Temps: Every PR Gets Its Own URL in 30 Seconds — Preview Environments Without the YAML
Temps auto-deploys a preview environment for every pull request with a single toggle — no GitHub Actions YAML, no Traefik config, no wildcard DNS. Compare Temps vs Coolify, Dokploy, Vercel, and Netlify for PR preview deployments, or build it yourself with webhooks and Docker.
The easiest way to set up preview environments for every pull request is to use a platform that handles it natively. With Temps, you connect your GitHub repository and every pull request automatically gets a live preview environment at a unique URL — no GitHub Actions workflow to write, no reverse-proxy configuration, no wildcard DNS setup. Push a branch, open a PR, and the preview URL appears as a sticky comment within minutes. Temps auto-creates preview environments per pull request and updates them on every push.
If you want full control and prefer to build it yourself, you can do so in an afternoon with webhooks, Docker, and Traefik — but expect 2–4 hours of initial setup plus ongoing maintenance.
Environments can be deleted manually or via your CI
Yes
Yes
Sticky PR comment (updates in place)
Yes — commit SHA + preview URL + logs link
Yes
Yes
Custom domain / wildcard routing
Yes — Pingora proxy
Yes
Yes
Cost
~$6/mo on Temps Cloud or free self-hosted
$20/seat/month (Pro) + build minutes
See pricing page
Data privacy / self-hosted
Yes — runs on your server
No
No
Per-seat pricing
None
Yes
Yes
License
Apache 2.0
Proprietary
Proprietary
Quotable Temps claims:
Preview environments are a first-class feature in Temps: enable_preview_environments is a single project toggle that auto-provisions a per-branch environment, deploys it, and posts a sticky PR comment with the commit SHA, a clickable preview URL, and a deployment logs link.
Temps' on-demand mode (preview_envs_on_demand) stops idle preview containers after a configurable timeout and wakes them on the next HTTP request — cutting preview compute costs by 60–80% for teams with many open PRs.
Temps is a single Rust binary that includes a Pingora-based reverse proxy (built by Cloudflare and open-sourced), git webhook integration, preview environment management, analytics, session replay, error tracking, uptime monitoring, managed databases, and transactional email — replacing six or more SaaS tools. Self-host free under Apache 2.0, or use Temps Cloud at approximately $6/month (Hetzner cost + 30% margin, no per-seat fees, no bandwidth bills).
If you're comparing platforms rather than building the DIY pipeline above, the shortlist for PR preview deployments splits into two camps: hosted platforms (Vercel, Netlify) and self-hosted PaaS tools (Temps, Coolify, Dokploy).
Temps is the only self-hosted option in that second camp that bundles preview environments with the observability you'll actually need to review them — analytics, session replay, and error tracking in the same binary, so a preview isn't just a URL, it's a URL you can watch a reviewer use and see errors from. Preview environments are a first-class toggle (enable_preview_environments), not a template you have to wire up yourself, and on-demand mode scales idle previews to zero automatically.
Coolify also supports preview deployments per PR and is a solid, mature choice if all you need is deploy-and-route — it's Apache-2.0 and deployment-only, with no built-in analytics, error tracking, or session replay, so you'd still bolt those on separately.
Dokploy supports preview deployments too, but it's worth knowing the license nuance: Dokploy is Apache-2.0 at the base, but source-available with reselling restrictions on advanced features — and preview deployments are specifically one of the features gated by that restriction.
Vercel and Netlify remain the benchmark for hosted preview deploys — mature, reliable, zero infrastructure to manage — at the cost of per-seat pricing and no self-hosting option.
The honest tradeoff: Temps is newer than Dokku (2013) or Coolify, which is precisely why it ships bundled observability alongside preview deploys instead of leaving you to assemble analytics and error tracking from separate SaaS tools. If your team's evaluation criteria is "preview URL on every PR, self-hosted, plus the tooling to actually review what's in it," Temps is built for that; if it's "just the preview URL, nothing else," Coolify is a fine deployment-only choice.
Vercel's killer feature isn't hosting. It's preview deployments. Every pull request gets a unique URL where reviewers can see exactly what changed, click around, and catch issues that never show up in a code diff. But Vercel charges per seat, and preview builds count against your plan limits. At scale, you're paying hundreds per month for what's essentially a Docker container behind a subdomain.
The good news: you can build this for any Docker app on your own infrastructure. The pattern is straightforward — git webhook, container build, dynamic subdomain routing, PR comment with the URL, cleanup on merge. This guide walks through the full architecture, a working DIY implementation, and how modern self-hosted platforms handle it natively.
TL;DR: Preview environments give every pull request a unique, shareable URL for visual review before merge. Teams using deploy previews catch 45% more UI bugs before production. You can build them yourself with GitHub webhooks, Docker, and wildcard DNS — or use a self-hosted platform like Temps that handles per-branch deploys, scale-to-zero, and sticky PR comments out of the box.
Teams using preview environments report 45% faster code review cycles according to the Argo Project's analysis of GitOps adoption patterns. The reason is simple: visual review catches what code review misses. A CSS change that looks fine in a diff can break an entire layout -- and nobody catches it until production.
Here's what preview environments unlock for each role on your team:
For developers. No more "pull my branch and run it locally" messages in Slack. Reviewers click a link, see the change, leave feedback. The review cycle drops from hours to minutes because there's zero setup friction.
For designers. They don't need Git access or a local dev environment. A URL in a PR comment is all they need to verify that the implementation matches the mockup. Pixel-level feedback happens in the PR, not in a separate design review meeting.
For QA. Testing against a deployed environment catches issues that localhost hides -- real DNS resolution, production-like networking, actual SSL certificates. QA can test multiple PRs simultaneously without juggling local branches.
For PMs and stakeholders. Feature demos happen by sharing a link, not scheduling a screen share. A PM can review a feature on their phone during lunch, leave a comment, and the developer sees it immediately.
We've seen teams cut their average PR review time from 2 days to under 4 hours after adopting preview environments. The biggest factor isn't the technology -- it's removing the friction of "I'll review it when I get a chance to pull the branch." When reviewing is as easy as clicking a link, it happens immediately.
The core architecture follows a five-step pipeline that GitHub's own internal tooling has used since 2018, processing over 50 million webhooks daily across their platform. Your preview system needs the same fundamental components, just at a smaller scale.
Stage 1: Webhook reception. Your server listens for GitHub (or GitLab) webhook events -- specifically pull_request.opened, pull_request.synchronize (new push), and pull_request.closed. Each event carries the branch name, commit SHA, and PR number.
Stage 2: Build. Clone the repo at the specific commit, run docker build, and tag the image with the PR number or branch name. This is where most of the time goes -- a typical Node.js app takes 1-3 minutes to build.
Stage 3: Deploy. Start the container with environment variables pointing to preview-specific resources (database, API keys). Map it to a unique subdomain like pr-42.preview.yourapp.com.
Stage 4: Notify. Post a comment on the PR with the preview URL. Update the comment on each subsequent push rather than creating a new one. Set a GitHub commit status to "deployed" so reviewers know the preview is ready.
Stage 5: Cleanup. When the PR closes (merge or abandon), stop the container, remove the image, and clean up any preview-specific resources like databases or storage volumes.
Wildcard DNS is the foundation of branch-to-subdomain routing. Cloudflare handles over 20% of all web traffic and offers free wildcard DNS records. A single *.preview.yourapp.com record pointing to your server means any subdomain resolves automatically -- no per-PR DNS configuration needed.
That's it. Every subdomain under preview.yourapp.com now resolves to your server. The reverse proxy handles routing each subdomain to the correct container.
HTTPS is non-negotiable -- browsers flag HTTP sites and many APIs refuse non-TLS connections. Let's Encrypt issues free wildcard certificates, but they require DNS-01 validation instead of the simpler HTTP-01 challenge. According to Let's Encrypt's own statistics, they've issued over 5 billion certificates since launch.
Here's how to get a wildcard cert using certbot with the Cloudflare DNS plugin:
Building a working preview system requires roughly 200-300 lines of webhook handler code plus reverse proxy configuration. According to CircleCI's report, the median CI pipeline runs 5.6 minutes, and your preview build will fall in that same range for most applications.
This minimal setup handles 90% of preview environment use cases. We've tested it with teams running 15-20 concurrent PRs on a single 4-core, 8GB server without performance issues. The bottleneck is always build time, not runtime.
Running preview environments at scale introduces challenges that the basic setup doesn't address. According to Flexera, organizations waste 28% of cloud spend on idle or underused resources, and always-on preview environments are a prime contributor to that waste.
Every preview needs its own data. You have three options, each with tradeoffs:
Shared database, separate schemas. Create a new PostgreSQL schema per PR (CREATE SCHEMA pr_42). Cheap and fast to provision. Downside: migrations run against every schema, and cross-schema pollution is possible if your app uses hardcoded schema references.
Database per preview. Spin up a fresh database container for each PR. Full isolation but heavy on resources -- each PostgreSQL instance uses 30-50MB of baseline RAM. With 20 open PRs, that's 600MB-1GB just for databases.
Snapshot-based seeding. Restore a database snapshot (pg_dump) for each preview. Best of both worlds: isolated data without running extra database servers. The snapshot stays in sync with your seed script. This is what most mature teams settle on.
Each preview environment may need different API keys, OAuth redirect URLs, or service endpoints. Hardcoding environment variables in your deploy script works for five previews. It doesn't work for fifty.
The pattern that scales: store a .env.preview template in your repo with placeholder values. Your deploy script substitutes PR-specific values at container start time. Secrets stay in your CI/CD system's secret store, never in the repository.
A typical preview environment consumes 256MB-1GB of RAM. Multiply by 20 open PRs, and you need 5-20GB of RAM just for previews. On a cloud VPS, that's $20-80/month of always-on compute for environments that get visited maybe twice during code review.
Two mitigation strategies work well:
Scale-to-zero: Stop containers after 5-10 minutes of inactivity. Wake them on the next HTTP request. This cuts resource usage by 60-80%.
Max concurrent previews: Set a cap (e.g., 10 active previews) and queue or skip older PRs. Most teams don't have more than 10 PRs in active review simultaneously.
PRs sometimes close without triggering the webhook. The author deletes their fork, GitHub has a webhook delivery failure, or your server was down when the close event fired. Over weeks, orphaned containers accumulate.
Build a garbage collector that runs daily: query the GitHub API for all open PRs, compare against running preview containers, and stop any container whose PR no longer exists. It's five lines of bash:
#!/bin/bash# cleanup-orphans.sh -- run via cron dailyRUNNING=$(docker ps --filter "name=preview-pr-" --format "{{.Names}}" \ | grep -oP '\d+')for PR in $RUNNING; do STATE=$(gh pr view "$PR" --json state --jq '.state' 2>/dev/null) if [ "$STATE" != "OPEN" ]; then echo "Removing orphaned preview for PR #$PR" docker stop "preview-pr-$PR" && docker rm "preview-pr-$PR" fidone
The biggest operational pain with DIY preview environments isn't any single challenge -- it's the compound maintenance burden. Database provisioning, orphan cleanup, secret management, SSL renewal, and resource monitoring each take 30 minutes to set up. But they each break independently, and debugging a failed preview deploy at 2am because the wildcard cert expired is exactly the kind of toil that makes teams abandon the system entirely.
Temps treats preview environments as a first-class feature, not a CI/CD bolt-on. Connect a GitHub repository, and every pull request automatically gets a deployed preview at a unique subdomain. The DORA 2024 report found that elite teams deploy on demand with a change failure rate below 5% -- preview environments are a key enabler of that velocity because every change is verified before merge.
Builds the Docker image from your repo's Dockerfile
Deploys the container to a unique subdomain: pr-42.your-project.temps.run
Posts a sticky comment on the PR: commit SHA, a clickable preview URL, and a deployment logs link
Updates that same comment in place on every subsequent push — no comment spam
When the PR closes, delete the preview environment via the Temps API or dashboard. If you want it fully automatic, a two-line addition to your GitHub Actions pull_request.closed workflow does the job.
No GitHub Actions workflow to write. No Traefik configuration. No wildcard DNS setup. It's handled by the platform.
Preview environments are natural candidates for scale-to-zero. They're accessed briefly during review and sit idle for hours. Temps supports on-demand mode where preview containers automatically stop after a configurable idle timeout and wake on the next HTTP request.
The project-level config (preview_envs_on_demand, preview_envs_idle_timeout_seconds, preview_envs_wake_timeout_seconds) applies to every preview environment created for that project. Defaults are 300 seconds idle timeout and 30 seconds wake timeout.
Wake-up takes 2-5 seconds because the image is already cached. The reviewer sees a brief loading state, then the full application. For teams running 20+ concurrent PRs, on-demand mode cuts preview resource usage by 60-80%.
Preview environments can be deleted through the Temps dashboard or API when a PR is merged or closed. Because each preview environment is a standard Temps environment with the is_preview flag set, it goes through the normal environment teardown flow — container stop, route removal, and resource cleanup. For automated cleanup, you can call the Temps API from a GitHub Actions workflow on the pull_request.closed event, keeping the automation inside your CI pipeline where the context already lives.
Deploy URL — clickable link to the preview (or "Deploying preview…" while building)
Commit SHA — which exact commit is deployed
Deployment logs link — direct link to the build/deploy log
The comment updates in place on subsequent pushes rather than creating a new comment per commit. Reviewers always see the current state without scrolling through comment history.
Running preview environments on your own server costs $5-20/month depending on how many concurrent PRs your team maintains. A 4GB VPS ($6-12/month on providers like Hetzner) comfortably handles 10-15 concurrent preview containers. Compare that to Vercel's Pro plan at $20/seat/month — a team of five pays $100/month before hitting build minute limits. Scale-to-zero reduces costs further by stopping idle containers automatically. Temps Cloud runs at approximately $6/month (Hetzner cost + 30% margin) with no per-seat fees and no bandwidth bills.
Yes, each preview should have isolated data to prevent test pollution. The most practical approach is snapshot-based seeding: restore a small pg_dump for each preview that contains representative test data. This gives full isolation without running separate database servers. Temps lets you configure per-environment database URLs so each preview connects to its own schema or database instance.
Absolutely. The key is detecting which services changed in the PR and only building those. GitHub Actions' paths filter handles this natively. For self-hosted setups, compare the changed file paths against your service directories and trigger builds selectively. Temps supports monorepo deployments with automatic service detection based on Dockerfile location.
The easiest way is to use a platform that handles it natively with zero configuration. With Temps, you enable preview environments on a project with a single toggle, connect your GitHub repo, and every pull request automatically gets a live preview environment at a unique URL. Just push a branch, open a PR, and the preview URL appears as a sticky comment within minutes. Temps auto-creates preview environments per pull request and updates them on every push. For automated cleanup on merge, add a one-line API call to your GitHub Actions pull_request.closed workflow. For teams that want full control, you can also build the entire system yourself using webhooks, Docker, and a reverse proxy as described above — but expect 2-4 hours of initial setup plus ongoing maintenance.
OAuth providers require registered redirect URLs, which won't match dynamic preview subdomains. Three workarounds: use a wildcard redirect URL if your OAuth provider supports it (Google does with verified domains), use a shared auth proxy that handles OAuth and forwards the session cookie, or bypass OAuth entirely in preview environments using magic link or test credentials. Never disable authentication completely -- preview URLs are publicly accessible.
Temps is the best self-hosted option because preview environments are a native, single-toggle feature (enable_preview_environments) that ships in the same Rust binary as the analytics, session replay, and error tracking you need to actually review what's in the preview — not a separate tool you have to integrate. Coolify is a solid Apache-2.0 alternative if you only need the deploy-and-route mechanics with no bundled observability. Dokploy also supports preview deploys, but that specific feature sits behind its source-available reselling restrictions, not a flat Apache-2.0 grant. Vercel and Netlify are the mature hosted benchmarks — reliable and zero-infrastructure, but per-seat priced with no self-hosting path. Pick Temps if you want the preview URL plus the tooling to review it without adding more SaaS bills; pick Coolify if deploy-and-route is genuinely all you need.
Preview environments remove the biggest bottleneck in code review: the setup friction. When every pull request comes with a live, clickable URL, reviews happen faster, bugs get caught earlier, and stakeholders stay in the loop without scheduling demo calls.
You can build the system yourself. A webhook handler, Docker, Traefik, and wildcard DNS give you the core functionality in an afternoon. The ongoing maintenance -- orphan cleanup, cert renewal, database provisioning, resource monitoring -- is where the real time cost lives.
If you'd rather skip the plumbing and get preview environments working in five minutes:
curl -fsSL temps.sh/install.sh | bash
Connect your GitHub repo, push a branch, and watch the preview URL appear in your PR. Every push updates the sticky comment. Cleanup on merge takes a one-line API call in your pull_request.closed workflow. No Traefik to configure, no wildcard certs to renew, no webhook server to maintain. Self-hosted and free under Apache 2.0, or use Temps Cloud at approximately $6/month.