DEV Community

Twisted-Code'r
Twisted-Code'r

Posted on

I built a free LocalStack alternative in Go — v0.6.0 is out with 37 AWS services

So I've been working on this project called CloudDev for a while now. It's basically a local AWS emulator — think LocalStack but free, open source, and a single Go binary with zero dependencies.

I just shipped v0.6.0 and wanted to share what's new.


Why I built this

Honestly? LocalStack's free tier kept getting more and more limited. Every time I needed a service it was "pro only". I just wanted to test my AWS code locally without spinning up real infrastructure or paying for a subscription.

So I started building CloudDev. The goal was simple — emulate the AWS services I actually use, make it work with the existing AWS CLI and SDKs without any config changes, and keep it as a single binary I can just run anywhere.


What's new in v0.6.0

This release was focused on infrastructure completeness. I added 8 new services:

  • Kinesis Data Streams — shards, records, iterators, the whole thing
  • Kinesis Firehose — delivery streams, PutRecord, PutRecordBatch
  • ECS — clusters, task definitions, run/stop tasks
  • ECR — repositories, image push/pull, auth token
  • CloudFront — distributions, origins, invalidations
  • AppSync — GraphQL APIs, data sources, schema upload
  • Athena — query execution, results, named queries
  • ACM — certificates, tags, mock PEM output

That brings the total to 37 AWS services across 47 modules.


Quick start

git clone https://github.com/Jeffrin-dev/CloudDev.git
cd CloudDev
go build -o clouddev .

./clouddev init my-app
cd my-app
../clouddev up
Enter fullscreen mode Exit fullscreen mode

That's it. All 37 services start up immediately.


Some examples

# Kinesis
aws --endpoint-url=http://localhost:4568 kinesis create-stream \
  --stream-name my-stream --shard-count 2

aws --endpoint-url=http://localhost:4568 kinesis put-record \
  --stream-name my-stream --data "hello" --partition-key "pk1"

# ECS
aws --endpoint-url=http://localhost:4561 ecs create-cluster \
  --cluster-name my-cluster

aws --endpoint-url=http://localhost:4561 ecs register-task-definition \
  --family my-task \
  --container-definitions '[{"name":"app","image":"nginx","memory":128}]'

# ECR
aws --endpoint-url=http://localhost:4562 ecr create-repository \
  --repository-name my-repo

aws --endpoint-url=http://localhost:4562 ecr get-authorization-token

# Athena
aws --endpoint-url=http://localhost:4564 athena start-query-execution \
  --query-string "SELECT * FROM my_table" \
  --query-execution-context Database=mydb

# ACM
aws --endpoint-url=http://localhost:4560 acm request-certificate \
  --domain-name example.com
Enter fullscreen mode Exit fullscreen mode

No endpoint configuration files, no fake credentials setup beyond the usual AWS_ACCESS_KEY_ID=test — just point the CLI at localhost and it works.


Full service list

Service Port
ACM 4560
ECS 4561
ECR 4562
CloudFront 4563
Athena 4564
S3 4566
AppSync 4567
Kinesis Data Streams 4568
DynamoDB 4569
DynamoDB Streams 4570
Kinesis Firehose 4571
API Gateway 4572
API Gateway v2 4573
Lambda 4574
SNS 4575
SQS 4576
Lambda Layers 4578
SES 4579
Dashboard 4580
CloudFormation 4581
CloudWatch Metrics 4582
SSM Parameter Store 4583
Secrets Manager 4584
Step Functions 4585
CloudWatch Logs 4586
EventBridge 4587
X-Ray 4588
Route53 4589
CloudWatch Events 4590
Bedrock 4591
STS 4592
IAM 4593
Rekognition 4594
Lambda Function URLs 4595
Cognito 4596
ElastiCache 4597/4598
KMS 4599

Web dashboard

There's also a web dashboard at localhost:4580 that shows all running services in real time. It flips red when the server goes down which is a small thing but honestly pretty useful when you're running tests.


How it's built

It's pure Go 1.22, no external runtime dependencies. Each AWS service is its own HTTP server listening on its port, routing requests by the X-Amz-Target header or REST path depending on the service protocol.

One thing I learned the hard way — AWS CLI doesn't always use the protocol the docs say it does. KMS, Kinesis, ECS, ECR all use JSON + X-Amz-Target. CloudFront uses REST + XML. AppSync uses REST + JSON. I had to sniff actual requests with nc a few times to figure out what the CLI was actually sending.


What's next

Not sure yet honestly. Maybe RDS, SQS dead letter queues, or better Lambda container support. Open to suggestions.

If you try it out let me know what breaks. There's definitely rough edges still.

GitHub:github.com/Jeffrin-dev/CloudDev

BUILD FOR DEVS

Top comments (0)