Railway

Deploying Pounce on Railway public networking

2 min read 380 words

Railway public networking expects the web process to listen on the Railway-providedPORT variable on 0.0.0.0. Railway terminates public TLS at the platform edge for HTTP services, so the usual Pounce deployment is plain HTTP inside the container withtrusted_hostsconfigured only after you confirm the ingress peer addresses for your service.

Start Command

Use a small entrypoint when your app needs programmatic config:

# railway_app.py
import os

import pounce
from myapp import app


if __name__ == "__main__":
    pounce.run(
        app,
        host="0.0.0.0",
        port=int(os.environ["PORT"]),
        workers=0,
        health_check_path="/health",
        log_format="json",
        access_log=False,
    )

Then set the Railway start command to:

python railway_app.py

For a plain import-string app that does not need custom ServerConfigvalues:

pounce myapp:app --host 0.0.0.0 --port "$PORT" --workers 0 --health-check-path /health --log-format json --no-access-log

Health Checks

Configure Railway's healthcheck path to/health, matching health_check_path="/health". Railway uses the service PORTfor healthcheck traffic, and healthchecks gate deployment activation rather than continuous monitoring.

If your application rejects unexpected hostnames, allow healthcheck.railway.appfor the health endpoint.

TLS And HTTP/3

Do not setssl_certfile, ssl_keyfile, or http3_enabled=Truefor Railway public HTTP unless you have a separate raw UDP/TCP networking design. Railway's public HTTP path provides platform TLS and forwards HTTP traffic to the process port.

Inside the ASGI scope,scope["scheme"] will be httpunless you configure trusted proxy headers and Railway forwardsX-Forwarded-Proto. Keep trusted_hostsempty until the ingress trust boundary for the deployment is known; untrustedX-Forwarded-*headers are stripped by default.

Graceful Deploys

Set Pounce shutdown and Railway drain windows together:

RAILWAY_DEPLOYMENT_DRAINING_SECONDS=30
pounce.run(
    app,
    host="0.0.0.0",
    port=int(os.environ["PORT"]),
    shutdown_timeout=25,
    health_check_path="/health",
)

The Railway drain window should be slightly longer than Pounce's shutdown_timeoutso in-flight requests can finish before the platform sends a hard kill.

Multi-Tenant Host Routing

For Chirp or LB Sonic style host routing, prefer deriving tenant identity from the ASGIHost header. Pounce preserves the request Hostdirectly, and when a trusted proxy suppliesX-Forwarded-Host, Pounce rewrites both the ASGI Host header and scope["server"]to that forwarded authority.

Confirm the actual Railway ingress headers for your deployed service before enablingtrusted_hosts. If those details are unknown, leave trusted_hosts empty and route tenants from the normalHostheader.

References