Heroku to PandaStack Migration: A Complete Walkthrough
If you're on Heroku and watching your bill climb, you're not alone. Since Heroku eliminated its free tier, developers have been actively searching for platforms that preserve the developer-friendly experience while offering better pricing. PandaStack is a cloud PaaS that covers static sites, Docker container deployments, managed databases (PostgreSQL, MySQL, Redis, MongoDB), cronjobs, edge functions, and managed WordPress/Drupal — all with GitHub-driven auto-deploys. This walkthrough covers every step of moving from Heroku to PandaStack.
Mapping Heroku Concepts to PandaStack
| Heroku | PandaStack |
|---|---|
| Web Dyno | Container Deployment |
| Worker Dyno | Container with background command |
| Heroku Postgres | Managed PostgreSQL |
| Heroku Redis | Managed Redis |
| Heroku Scheduler | Cronjobs |
| Config Vars | Environment Variables |
| Buildpack | Dockerfile |
| Pipeline | GitHub branch-based deploys |
Phase 1: Prepare Your Heroku App for Export
# Install Heroku CLI if not already installed
npm install -g heroku
# Log in and verify your app
heroku auth:login
heroku apps:info --app your-app-name
# List all add-ons (so you know what to replace)
heroku addons --app your-app-name
# Export all config vars to a local reference file
heroku config --shell --app your-app-name > heroku-config-backup.txt
# View scheduler tasks
heroku addons:open scheduler --app your-app-nameDocument every scheduler task: its command, its schedule, and which dyno type it runs on.
Phase 2: Export Your Heroku Postgres Database
# Capture a fresh backup
heroku pg:backups:capture --app your-app-name
# Check backup status
heroku pg:backups --app your-app-name
# Download the backup
heroku pg:backups:download --app your-app-name --output heroku-postgres.dump
# Verify integrity
pg_restore --list heroku-postgres.dump | head -30Phase 3: Create Your Dockerfile
Heroku buildpacks automatically detect your runtime. PandaStack uses Docker, so you need to make this explicit. Here's a production-ready Dockerfile for a Node.js Express app:
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "src/index.js"]Also create a .dockerignore to keep image sizes small:
node_modules
.git
.env
*.logPhase 4: Provision PandaStack Resources
1. Create a PostgreSQL database at [dashboard.pandastack.io](https://dashboard.pandastack.io) → Databases → New PostgreSQL
2. Restore your Heroku backup:
export PS_DB="postgresql://user:password@pandastack-host:5432/mydb"
pg_restore --no-acl --no-owner --verbose --jobs=4 -d "$PS_DB" heroku-postgres.dump
# Verify
psql "$PS_DB" -c "dt"
psql "$PS_DB" -c "SELECT COUNT(*) FROM users;"3. Create Redis if needed:
Navigate to Databases → New Redis. Copy the Redis URL for your environment variables.
Phase 5: Configure and Deploy
npm install -g @pandastack/cli
panda login
# Initialize a new PandaStack project linked to your GitHub repo
panda init
# Set environment variables (from your heroku-config-backup.txt reference)
panda env set NODE_ENV=production
panda env set DATABASE_URL="$PS_DB"
panda env set REDIS_URL=redis://user:pass@pandastack-redis:6379
panda env set JWT_SECRET=your-jwt-secret
# ... add all other vars from your Heroku configPandaStack connects to GitHub and auto-deploys on every push. No manual deploy steps needed after initial setup.
Phase 6: Recreate Scheduler Tasks as Cronjobs
For every task in Heroku Scheduler, create a PandaStack cronjob:
# Example: daily database cleanup at 2am UTC
panda cronjob create --name db-cleanup --image ghcr.io/your-org/your-app:latest --schedule "0 2 * * *" --command "node scripts/cleanup.js"
# Example: hourly cache refresh
panda cronjob create --name cache-refresh --image ghcr.io/your-org/your-app:latest --schedule "0 * * * *" --command "node scripts/refresh-cache.js"
# List all cronjobs to confirm
panda cronjobs listPhase 7: Smoke Test Before DNS Cutover
# Test core endpoints
curl -I https://your-app.pandastack.io
curl https://your-app.pandastack.io/api/health
curl https://your-app.pandastack.io/api/users -H "Authorization: Bearer test-token"
# Verify database reads
curl https://your-app.pandastack.io/api/products | jq '.total'Once all tests pass, update your DNS CNAME to point to PandaStack and monitor error rates for 24 hours. The migration is complete. With a free tier available and paid plans starting at $12/mo, PandaStack typically cuts Heroku bills by 60-70% for comparable workloads.