Getting Started
This guide will help you install Hornbeam and run your first Python web application on the BEAM.
Requirements
- Erlang/OTP 27+
- Python 3.12+ (3.13+ recommended for free-threading)
- C compiler (gcc or clang)
Installation
Add Hornbeam to your rebar.config:
{deps, [
{hornbeam, {git, "https://github.com/benoitc/hornbeam.git", {branch, "main"}}}
]}.
Compile:
rebar3 compile
Quick Start
1. Create a Python Application
Create a simple WSGI application:
# myapp.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return [b'Hello from Hornbeam!']
2. Start Hornbeam
%% Start the shell
rebar3 shell
%% Start hornbeam with your app
hornbeam:start("myapp:application").
3. Test It
curl http://localhost:8000
# Hello from Hornbeam!
Running ASGI Applications
For async applications (FastAPI, Starlette):
# myapp.py
async def application(scope, receive, send):
await send({
'type': 'http.response.start',
'status': 200,
'headers': [[b'content-type', b'text/plain']],
})
await send({
'type': 'http.response.body',
'body': b'Hello from ASGI!',
})
hornbeam:start("myapp:application", #{worker_class => asgi}).
Running Existing Frameworks
Flask
# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello from Flask on Hornbeam!'
# WSGI application
application = app
hornbeam:start("app:application").
FastAPI
# app.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello from FastAPI on Hornbeam!"}
hornbeam:start("app:app", #{worker_class => asgi}).
Django
# myproject/wsgi.py (Django generates this)
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
hornbeam:start("myproject.wsgi:application", #{
pythonpath => [".", "myproject"]
}).
Configuration
Basic configuration options:
hornbeam:start("myapp:application", #{
%% Server binding
bind => "0.0.0.0:8000",
%% Protocol: wsgi or asgi
worker_class => wsgi,
%% Number of Python workers
workers => 4,
%% Request timeout (ms)
timeout => 30000,
%% Python module search paths
pythonpath => [".", "src"]
}).
See Configuration Reference for all options.
Using Erlang Features
The real power of Hornbeam is accessing Erlang from Python:
Shared State (ETS)
from hornbeam_erlang import state_get, state_set, state_incr
def application(environ, start_response):
# Atomic counter - safe with millions of concurrent requests
views = state_incr('page_views')
# Cache expensive computations
data = state_get('cached_data')
if data is None:
data = expensive_computation()
state_set('cached_data', data)
start_response('200 OK', [('Content-Type', 'text/plain')])
return [f'Views: {views}'.encode()]
Distributed RPC
from hornbeam_erlang import rpc_call, nodes
def application(environ, start_response):
# Call function on remote node
result = rpc_call('ml@gpu-server', 'model', 'predict', [data])
start_response('200 OK', [('Content-Type', 'application/json')])
return [json.dumps(result).encode()]
See the Erlang Integration Guide for more.
Next Steps
- WSGI Guide - Full WSGI protocol details
- ASGI Guide - Async apps and WebSocket
- Erlang Integration - ETS, RPC, Pub/Sub
- Examples - Complete working examples