Skip to content

Migration Guide

This guide helps you migrate applications to Hop3 from other platforms.

Table of Contents


From Heroku

Hop3 is designed to be Heroku-compatible at the Procfile level, making migration straightforward.

Step 1: Copy Your Procfile

If you have a Heroku Procfile, it should work as-is in Hop3:

# Your existing Heroku Procfile
web: gunicorn myapp.wsgi:application
worker: celery -A myapp worker

Just copy it to your Hop3 application directory.

Step 2: Migrate Environment Variables

Export your Heroku config:

heroku config -s --app myapp > .env

Set environment variables in Hop3:

# Using hop3-cli
hop3 config set myapp $(cat .env)

# Or add to hop3.toml
[env]
DATABASE_URL = "postgresql://..."
SECRET_KEY = "..."

Step 3: Migrate Addons

Map Heroku addons to Hop3 services:

Heroku Postgres:

# Heroku
heroku addon create heroku-postgresql:standard-0

# Hop3
hop3 addon create postgres myapp-db
hop3 addon attach myapp myapp-db

Heroku Redis:

# Heroku
heroku addon create heroku-redis:premium-0

# Hop3
hop3 addon create redis myapp-cache
hop3 addon attach myapp myapp-cache

Step 4: Deploy

hop3 deploy myapp

Heroku → Hop3 Mapping

Heroku Hop3 Notes
heroku create hop3 app launch <repo> myapp Create app from repo
git push heroku main hop3 deploy myapp Deploy code
heroku config set hop3 config set Set env vars
heroku addon create heroku-postgresql hop3 addon create postgres Database
heroku addon create heroku-redis hop3 addon create redis Cache
heroku ps hop3 ps myapp Process status
heroku logs -t hop3 app logs myapp View logs
heroku restart hop3 app restart myapp Restart app

Common Gotchas

1. Buildpacks

Heroku uses buildpacks for detecting app type. Hop3 also supports buildpacks but provides native build strategies:

# Heroku
heroku buildpacks:set heroku/python

# Hop3
# Automatic detection, or specify in hop3.toml:
[build]
buildpack = "python"

2. Procfile Commands

Some Heroku-specific commands may need adjustment:

# Heroku release phase
release: python manage.py migrate

# Hop3 equivalent (use prerun)
prerun: python manage.py migrate

3. Port Binding

Heroku sets $PORT dynamically. Hop3 also provides $PORT:

# Works on both Heroku and Hop3
port = int(os.environ.get("PORT", 8000))

From Fly.io

Fly.io uses fly.toml for configuration. You can migrate to Hop3's hop3.toml format.

Step 1: Convert fly.toml to hop3.toml

Fly.io fly.toml:

app = "myapp"

[build]
  builder = "paketobuildpacks/builder:base"

[env]
  PORT = "8080"

[[services]]
  internal_port = 8080
  protocol = "tcp"

Hop3 hop3.toml:

[metadata]
id = "myapp"

[run]
start = "python app.py"

[env]
PORT = "8080"

[port]
web = 8080

Step 2: Migrate Services

Fly.io Postgres:

# Fly.io
fly postgres create --name myapp-db

# Hop3
hop3 addon create postgres myapp-db
hop3 addon attach myapp myapp-db

Step 3: Deploy

hop3 deploy myapp

Fly.io → Hop3 Mapping

Fly.io Hop3 Notes
fly launch hop3 app launch <repo> myapp Create app from repo
fly deploy hop3 deploy myapp Deploy code
fly secrets set hop3 config set Set secrets
fly postgres create hop3 addon create postgres Database
fly status hop3 app status myapp App status
fly logs hop3 app logs myapp View logs
fly restart hop3 app restart myapp Restart app

From Procfile to hop3.toml

If you want more control than Procfile provides, migrate to hop3.toml.

Automatic Migration

Use the built-in migration command:

# Dry run - see what would be generated
hop3 config migrate procfile /path/to/app --dry-run

# Actually migrate
hop3 config migrate procfile /path/to/app

This will: 1. Parse your existing Procfile 2. Generate a hop3.toml file 3. Create a backup of your Procfile (Procfile.bak)

Manual Migration

Before (Procfile):

prebuild: npm ci && npm run build
prerun: npm run migrate
web: node dist/server.js
worker: node dist/worker.js

After (hop3.toml):

[metadata]
id = "my-app"
version = "1.0.0"

[build]
before-build = ["npm ci", "npm run build"]

[run]
start = "node dist/server.js"
before-run = "npm run migrate"

# Note: 'worker' process needs manual integration
# Consider using a process manager or separate deployment

Why Migrate to hop3.toml?

Advantages of hop3.toml: - More expressive (metadata, health checks, backups) - Better for complex applications - Supports environment-specific configuration - Native TOML validation

Keep using Procfile if: - You have a simple application - You want maximum Heroku compatibility - You prefer convention over configuration

Using Both Together

You can use both Procfile and hop3.toml together:

# Procfile - Basic worker definitions
web: gunicorn app:app
worker: celery worker
# hop3.toml - Advanced configuration
[metadata]
id = "my-app"

[build]
before-build = "pip install -r requirements.txt"

[healthcheck]
path = "/health/"
interval = 60

[[provider]]
name = "postgres"
plan = "standard"

Hop3 will merge these configurations with hop3.toml taking precedence.


Environment-Specific Configuration

Hop3 uses a single hop3.toml configuration file. Environment-specific settings are handled through environment variables, which you can set differently per deployment.

Production Configuration (hop3.toml)

# hop3.toml - used for all environments
[metadata]
id = "myapp"

[run]
start = "gunicorn app:app --workers 4"

[healthcheck]
enabled = true
path = "/health/"

Environment Variables for Different Environments

# Production
hop3 config set myapp LOG_LEVEL=info

# Development/staging (local testing)
LOG_LEVEL=debug flask run --reload

For local development, run your app directly without Hop3. For deployed environments, use hop3 config set to configure environment-specific variables.


Validation

After migration, validate your configuration:

# Check app configuration
hop3 config show myapp

# Deploy and verify
hop3 deploy myapp
hop3 app status myapp
hop3 app logs myapp

Need Help?