Migrate from AWS
AWS has ~200 services; we have 6 substrate primitives. This guide maps the most common production-AWS surfaces onto Joule Cloud equivalents. The pattern: each AWS service splits into "the thing it does" + "a billing model"; we provide the thing and drop the punitive billing.
Service-by-service map
| AWS service | Joule Cloud equivalent | Migration notes |
|---|---|---|
| EC2 (general-purpose compute) | Compute | Bring an OCI image. Single binary works; full container works. See migration steps below. |
| Lambda (serverless functions) | Functions | JS/Python/Rust/WASI runtimes. Same handler shape (request in, response out). |
| S3 | Object Store | S3-API compatible. Dedicated guide. |
| RDS Postgres | JouleDB | Postgres-wire compatible. pg_dump → psql just works. |
| Bedrock (AI inference) | Inference | OpenAI-shape; "auto" for model selection. |
| CloudFront / Route 53 | Built-in routing | Set a route block in invisible.hcl; DNS is via Cloudflare or your own. |
| SQS / SNS | Functions + queue trigger | One-line: --on queue/jobs. Light queues at launch; partial parity with SQS feature surface. |
| EKS / ECS | Just deploy containers | You don't configure a cluster; the mesh is the cluster. |
| IAM | Tokens with scopes | Per-token scopes (read / deploy / billing-admin / inference-only). No role-tree. |
| CloudWatch | Live joule + log stream in console | Free; not metered. Export via jc logs --tail. |
| Glue / Athena (analytics) | JouleDB columnar surface | Arrow-IPC + DuckDB-compatible SQL. |
| KMS | Token + SSE-C | Bring your own key for object encryption; key management coming. |
EC2 → Compute
Lift-and-shift, the literal way
Containerize the workload, declare it, deploy.
# 1. Make a Dockerfile if you don't have one
FROM debian:bookworm-slim
COPY ./myapp /usr/local/bin/myapp
EXPOSE 8080
CMD ["/usr/local/bin/myapp"]
# 2. Build + push
docker build -t ghcr.io/me/myapp:1.0 .
docker push ghcr.io/me/myapp:1.0
# 3. invisible.hcl
workload "myapp" {
image = "ghcr.io/me/myapp:1.0"
region = "auto"
cpu = "2 vCPU"
memory = "4 GB"
}
route "myapp.example.com" {
to = workload.myapp
}
# 4. Deploy
invisible deploy
What you drop
- Reserved Instance contracts — we don't do those
- Per-region replication YAML —
region = "auto"handles it - Application Load Balancer config — the
routeblock is the LB - Security Group rules — tokens replace IP-based ACLs
Lambda → Functions
Lambda handlers ((event, context) → response) map onto Functions. The handler signature differs slightly (we use the standard Request / Response objects), but the work the handler does is the same.
// Lambda
- export const handler = async (event, context) => {
- const body = JSON.parse(event.body);
- return { statusCode: 200, body: JSON.stringify({ hello: body.name }) };
- };
// Joule Cloud Functions
+ export default async function (req) {
+ const body = await req.json();
+ return Response.json({ hello: body.name });
+ }
RDS → JouleDB
# dump
pg_dump $RDS_URL --no-owner --no-acl > backup.sql
# create JouleDB instance
jc db create main --region eu-fi --size 100GB
# restore
psql "postgresql://jc_…@db.greenjoules.cloud:5432/main" < backup.sql
The unsexy parts: networking, IAM, observability
- Networking. Joule Cloud workloads default to public ingress over HTTPS via
routeblocks. Internal communication between your workloads is on the mesh's private network — zero egress, zero config. - IAM. One token per service, scoped to what it needs (inference-only, deploy, billing-admin, full). Token rotation is one click in the portal. No role-trust chains, no STS, no AssumeRole.
- Observability. Logs stream live in the console and via
jc logs --tail. Metrics include joules + carbon as first-class series. Push to your own backend (Prometheus / OTLP) with one workflow config.
What this is not
If you need DynamoDB Streams, Step Functions visual workflows, AppSync managed GraphQL, Glue ETL jobs, or other AWS-shaped specialty services, we don't have direct equivalents. Either keep those on AWS and migrate the rest, or use open alternatives on top of Compute / Functions / JouleDB.