Heroku

Move from Heroku to Europe.

run.zero works like Heroku, with buildpacks, a Procfile and DATABASE_URL, on servers in Germany. The only new file is a run-zero.yaml, but your data does not move by itself.

Needs the Developer plan, the free plan only covers websites. Pricing · Check the limits first

  • Procfile stays
  • DATABASE_URL stays
  • Servers in Nuremberg
claude · run-zero-examples/heroku-migration

> Deploy the heroku-migration folder to run.zero.

runzero_create_appdoneexample-heroku

runzero_push_filesdoneone commit

runzero_deploydoneservices and Postgres created

runzero_wait_for_builddonelive

live at https://web-example-heroku-b24cc7f1.run-zero.de

The session that created the live demo, with the real MCP tools.
How it works

Your app in four steps.

Tested with the Flask app that runs live.

  1. 01

    Check the Procfile

    The web line must listen on $PORT, just like on Heroku. It stays as it is.

  2. 02

    Translate the addons

    Heroku Postgres becomes the Postgres addon. The platform sets DATABASE_URL, so no code changes.

    run-zero.yaml
    version: "1"services:  web:    port: 8080addons:  db:    type: postgres    attachTo: [web]
  3. 03

    Copy your config vars

    Set the values from heroku config as secrets in the dashboard or with runzero_set_secrets. The service restarts afterwards.

  4. 04

    Create an account and deploy

    Create an account, connect your agent with this command, then sign in from Claude Code with /mcp and Authenticate.

    • Then tell your agent: deploy this repo to run.zero.
    Without an agent

    Create the app in the dashboard and connect your GitHub repo. Every push rebuilds.

    Connect Claude Code
    claude mcp add --transport http \  -s user run-zero \  https://api.run-zero.de/mcp \  --client-id runzero-cli \  --callback-port 53761

After 1 to 3 minutes the app is live at https://web-<app>.run-zero.de. Check a route of your app, in the example /api/health. If the build is red, runzero_get_build_logs tells you why.

Moving data: these steps bring your app, not your data. There is no dump import, single SQL statements go through the SQL console or runzero_db_query. For a large database, this is not a finished migration today.

Files

A typical Heroku app.

Flask, gunicorn and Postgres, only the config is new.

The same web line as on Heroku.

Example on GitHub(opens in a new tab)
heroku-migration/Procfile
web: gunicorn app:app --bind 0.0.0.0:$PORT

Counts visits in Postgres through DATABASE_URL.

Example on GitHub(opens in a new tab)
heroku-migration/app.py
# A typical Heroku app: Flask, gunicorn from the Procfile, Postgres from DATABASE_URL.import osimport psycopgfrom flask import Flask, jsonifyapp = Flask(__name__)DATABASE_URL = os.environ.get("DATABASE_URL")def count_visit() -> int:    # run.zero injects DATABASE_URL with sslmode=require, psycopg accepts it as is.    with psycopg.connect(DATABASE_URL) as conn:        conn.execute("CREATE TABLE IF NOT EXISTS visits (id serial PRIMARY KEY, at timestamptz DEFAULT now())")        conn.execute("INSERT INTO visits DEFAULT VALUES")        return conn.execute("SELECT count(*) FROM visits").fetchone()[0]@app.get("/")def index():    visits = count_visit() if DATABASE_URL else "no database attached"    return f"""<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>From Heroku to run.zero</title></head><body style="font-family:system-ui,sans-serif;max-width:640px;margin:64px auto;padding:0 24px"><h1>From Heroku to run.zero</h1><p>Same Procfile, same DATABASE_URL. Visits stored in Postgres: <strong id="visits">{visits}</strong></p><p><a href="/api/health">/api/health</a></p></body></html>"""@app.get("/api/health")def health():    return jsonify(status="ok", database=bool(DATABASE_URL), platform="run.zero")

flask, gunicorn and psycopg.

Example on GitHub(opens in a new tab)
heroku-migration/requirements.txt
flask==3.1.0gunicorn==23.0.0psycopg[binary]==3.2.3
Translation

Heroku concepts on run.zero.

What stays and what has another name.

BuildpacksPaketo buildpacks for Node, Python, Go, PHP, Java
ProcfileProcfile, unchanged
DynoService with 0 to 10 replicas, depending on the plan
Heroku PostgresPostgres addon with DATABASE_URL
Config varsSecrets on the service or the app
git push heroku mainPush to the connected repo, or runzero_push_files
app.json, pipelinesrun-zero.yaml, preview addresses for changes
Limits

What does not work today.

So the move holds no surprises.

  • Needs the Developer plan

    Free has no server apps and no Postgres, a deploy stops with an error.

    See pricing
  • Addons: Postgres and Keycloak

    Heroku Redis, Kafka or marketplace addons do not exist here.

  • No dump import

    There is no import for a dump. Small datasets go in as SQL through the SQL console or runzero_db_query.

  • No app.json

    Describe services, ports and addons in run-zero.yaml.

Operations

What you stop doing yourself.

Builds, HTTPS, the database and backups run on the platform.

  • Data stays in Germany

    Servers and backups at Hetzner in Nuremberg. With a data processing agreement.

  • HTTPS by default

    Every service gets an address on run-zero.de, custom domains a Let’s Encrypt certificate.

  • Postgres as an addon

    One entry in run-zero.yaml, DATABASE_URL arrives as an environment variable.

  • No lock-in

    Your code stays in your repo, the database is a dump you can download.

Questions.

About the move.

Do I have to change my code?

Usually not. Procfile, $PORT and DATABASE_URL work as on Heroku. Only check the addons you use.

Does DATABASE_URL work with SSL?

Yes. The URL carries sslmode=require against a self-signed certificate. psycopg accepts it as is, node-postgres needs ssl: { rejectUnauthorized: false } and a URL without sslmode.

Is there a replacement for Heroku Scheduler?

We have not tested one, the example only shows the web process.

Can I leave again?

Yes. The code lives in your repo, and the dashboard offers the database as a pg_dump download.

Where do the servers run?

At Hetzner in Nuremberg, backups included. With a data processing agreement.

More guides

All guides

Your code. Live on run.zero.

One website is free, no credit card. Apps with a server, a database and a custom domain come with the Developer plan.