Running Aleph
Aleph separates describing a backend from running it. The language (the SDK, the CLI, and the manifest format) is open source. Running a manifest is the job of a runtime: any program that embeds the open-source core and provides storage, authentication, and integration providers.
What the core gives a runtime
aleph-core is one Rust library, used natively or as WebAssembly. It covers four things.
Validation and analysis
- Validates a manifest and computes the worst case of every route and handler.
- Classifies a new manifest against the deployed one, with a migration plan.
Execution
- Executes requests: routing, authorization, input validation, and one metered, serializable transaction per request.
- Processes the outbox: handlers, jobs, schedules, workflow steps, and deliveries, with retries and backoff.
Isolation
- Builds every key inside the tenant's keyspace.
Files
- Signs upload and download URLs for buckets, and checks them: signature, expiry, content type, and size.
- Records finished uploads and runs their
onUploadhandlers.
Testing
- Runs route examples, as
aleph testdoes.
What a runtime provides
| Piece | The interface | What aleph dev uses |
|---|---|---|
| Storage | An ordered, transactional key-value store (Store) | An in-memory store, optionally saved to a file |
| Callers | Who is calling, already authenticated (Caller) | Headers like x-aleph-user |
| Integrations | Calls (Integrations) and deliveries (Sink) | Mocks you set, and an activity log |
| Secrets | Secret values by name (Secrets) | --secret NAME=value |
| File storage | Somewhere to keep file bytes, and a gateway that serves signed URLs (BlobSigner) | Files in memory (or next to --data), served under /_aleph/blobs/ |
| Time and ids | A clock and an id source (Env) | The system clock |
A blob gateway is small, because the core decides everything: give the engine a BlobSigner with the gateway's base URL and a signing secret. On an upload, call check_upload before accepting the bytes, store them, then receive_upload. On a download, call authorize_download and serve the bytes with the file's content type. Delete a file's bytes when a deleteBlob delivery arrives. Where the bytes live (object storage, disk) is up to the runtime.
The core never runs author TypeScript, and a runtime doesn't need to either. It consumes the manifest alone. An app update is a new manifest, not a new build.
The same core everywhere
aleph dev, aleph test, the conformance suite, and any production runtime all execute the same core. A result you get locally is the result a runtime gives.
Observability
Every operation in an Aleph app is a known, built-in operation, so the runtime can observe the app without you adding logging or tracing code.
What every request reports
Each response carries what the request actually used: reads, writes, operations, bytes read, effects, integration calls, and memory. That's always within the route's static bound. aleph dev returns it in an x-aleph-usage header and in its log:
POST /orders → 201 post_orders (reads 3, writes 4, ops 61) 0.41msRequests that had to retry because of contention say so (hot: 2 conflict retries), which points at a hot key worth sharding.
Errors are declared outcomes
Business errors aren't exceptions. They're declared on the route (errors({ notFound: err.notFound() })), so every possible failure has:
- a name
- a status
- a message
- optionally, typed details
They show up in OpenAPI, in generated clients, and in dashboards by name. Failures that aren't business errors, like a broken invariant, a unique conflict, or a run over its limits, have stable built-in codes too.
Logs when you want them
$.log("total", total) records a labelled value. It never changes what the plan does, and it's returned with the response and shown by aleph dev.
Async work
Background work is reported the same way:
- handler runs, with their usage
- retries and dead letters
- deliveries
- integration calls
In aleph dev, the inspection API (GET /__aleph/activity) streams all of it, and the example apps' inspector panel draws it next to each route's bounds.