Migrate from Heroku
Heroku and Temps use the same mental model — push code, platform builds and runs it. The main migration work is converting your Procfile, moving your Postgres data, and replacing any Heroku add-ons.
Procfile → Temps
Heroku uses a Procfile to define process types:
web: node server.js
worker: node worker.js
release: node migrate.js
Temps runs your app as a container. If you have a Procfile, add a Dockerfile that calls the same command:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
For the web process, Temps sets the PORT environment variable — make sure your app binds to process.env.PORT:
const port = process.env.PORT || 3000;
app.listen(port);
Workers
For background workers, deploy them as a separate Temps project pointing at the same repository. Set the start command to node worker.js in Project → Settings → Build & Deploy.
Release phase
The release process (migrations before deploy) maps to Pre-deploy commands in Temps — run your migration script there so it executes before traffic shifts to the new container.
Buildpacks
Heroku buildpacks auto-detect and configure your runtime. Temps does the same: it detects Node.js, Python, Ruby, Go, Java, and more without any config.
If your app uses a custom buildpack, add a Dockerfile instead. Temps treats any repo with a Dockerfile as a Docker project.
Environment Variables
Export from Heroku CLI:
heroku config -s --app your-app-name > .env
Then add them in Temps → Project → Settings → Environment Variables.
Remove Heroku-injected variables before importing — they won't apply on Temps:
| Heroku variable | Action |
|---|---|
DATABASE_URL | Replace with your new Postgres URL |
HEROKU_APP_NAME | Remove or replace with your own |
HEROKU_RELEASE_VERSION | Remove |
WEB_CONCURRENCY | Remove (Temps manages concurrency) |
PORT | Remove — Temps injects this automatically |
Heroku Postgres Migration
Export data
# Create a backup on Heroku
heroku pg:backups:capture --app your-app-name
# Download the backup
heroku pg:backups:download --app your-app-name
This creates a latest.dump file in the current directory.
Restore to your new database
pg_restore --verbose --no-acl --no-owner \
-d "postgresql://postgres:yourpassword@localhost:16432/yourdb" \
latest.dump
Test the restore against a scratch database first. Heroku's pg_dump uses the
custom format (-Fc) which pg_restore handles, but verify row counts match
before pointing your app at the new database.
Update DATABASE_URL in your Temps environment variables to the new connection string.
Add-on Alternatives
Heroku add-ons that are commonly used and their Temps-compatible replacements:
| Heroku Add-on | Alternative |
|---|---|
| Heroku Postgres | Temps Managed Services, Neon, or Supabase |
| Heroku Redis | Temps Managed Services (Redis container) |
| Sendgrid | Resend, Postmark, or AWS SES |
| Papertrail | Temps built-in log streaming |
| New Relic / Librato | Temps built-in monitoring and uptime checks |
| Rollbar / Bugsnag | Temps built-in error tracking (Sentry-compatible DSN) |
| Scheduler | Temps Cron Jobs |
| Cloudinary | Cloudflare Images or self-hosted Imgproxy |
Deploy
# Install Temps if not already done
curl -fsSL https://temps.sh/deploy.sh | bash
- Go to Projects → New Project in the Temps console
- Connect your Git repository
- Add environment variables
- If using a Dockerfile, Temps detects it automatically; otherwise set your build and start commands
- Click Deploy
Custom Domains
Heroku routes traffic through yourapp.herokuapp.com. On Temps:
- Go to Project → Settings → Domains → Add Domain
- Add the DNS records shown (A or CNAME)
- Temps provisions TLS automatically via Let's Encrypt
Remove the Heroku domain from your app's config once you've verified the Temps deployment is healthy.
Verify and Cut Over
- Test your app at the Temps preview URL end-to-end (auth, database reads/writes, background jobs)
- Cut DNS over to Temps
- Keep your Heroku app in maintenance mode (not deleted) for 48 hours as a fallback