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 serviceJoule Cloud equivalentMigration notes
EC2 (general-purpose compute)ComputeBring an OCI image. Single binary works; full container works. See migration steps below.
Lambda (serverless functions)FunctionsJS/Python/Rust/WASI runtimes. Same handler shape (request in, response out).
S3Object StoreS3-API compatible. Dedicated guide.
RDS PostgresJouleDBPostgres-wire compatible. pg_dumppsql just works.
Bedrock (AI inference)InferenceOpenAI-shape; "auto" for model selection.
CloudFront / Route 53Built-in routingSet a route block in invisible.hcl; DNS is via Cloudflare or your own.
SQS / SNSFunctions + queue triggerOne-line: --on queue/jobs. Light queues at launch; partial parity with SQS feature surface.
EKS / ECSJust deploy containersYou don't configure a cluster; the mesh is the cluster.
IAMTokens with scopesPer-token scopes (read / deploy / billing-admin / inference-only). No role-tree.
CloudWatchLive joule + log stream in consoleFree; not metered. Export via jc logs --tail.
Glue / Athena (analytics)JouleDB columnar surfaceArrow-IPC + DuckDB-compatible SQL.
KMSToken + SSE-CBring 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

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

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.