{"id":48632974,"url":"https://github.com/floci-io/floci","last_synced_at":"2026-05-10T20:00:06.555Z","repository":{"id":344693023,"uuid":"1160497244","full_name":"floci-io/floci","owner":"floci-io","description":"Light, fluffy, and always free - AWS Local Emulator ","archived":false,"fork":false,"pushed_at":"2026-05-08T22:24:21.000Z","size":4790,"stargazers_count":4429,"open_issues_count":13,"forks_count":316,"subscribers_count":23,"default_branch":"main","last_synced_at":"2026-05-09T00:23:47.832Z","etag":null,"topics":["aws","aws-emulation","devops","docker","ec2","ecs","localstack","s3","sqs","testcontainers"],"latest_commit_sha":null,"homepage":"https://floci.io","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/floci-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["hectorvent"]}},"created_at":"2026-02-18T02:28:29.000Z","updated_at":"2026-05-08T23:20:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"0c50f97a-7b9d-45d5-b062-0b85a2c846b9","html_url":"https://github.com/floci-io/floci","commit_stats":null,"previous_names":["hectorvent/floci","floci-io/floci"],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/floci-io/floci","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floci-io%2Ffloci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floci-io%2Ffloci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floci-io%2Ffloci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floci-io%2Ffloci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/floci-io","download_url":"https://codeload.github.com/floci-io/floci/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floci-io%2Ffloci/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32869721,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"ssl_error","status_checked_at":"2026-05-10T13:40:02.145Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-emulation","devops","docker","ec2","ecs","localstack","s3","sqs","testcontainers"],"created_at":"2026-04-09T06:03:09.229Z","updated_at":"2026-05-10T20:00:06.538Z","avatar_url":"https://github.com/floci-io.png","language":"Java","funding_links":["https://github.com/sponsors/hectorvent"],"categories":["Java","aws"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"floci_banner.svg\" alt=\"Floci\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/floci-io/floci/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/floci-io/floci?label=latest%20release\u0026color=blue\" alt=\"Latest Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/floci-io/floci/actions/workflows/release.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/floci-io/floci/release.yml?label=build\" alt=\"Build Status\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/hectorvent/floci\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/hectorvent/floci?label=docker%20pulls\" alt=\"Docker Pulls\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/hectorvent/floci\"\u003e\u003cimg src=\"https://img.shields.io/docker/image-size/hectorvent/floci/latest?label=image%20size\" alt=\"Docker Image Size\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-green\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/floci-io/floci/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/floci-io/floci?style=flat\" alt=\"GitHub Stars\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/floci-io/floci/graphs/contributors\"\u003e\u003cimg src=\"https://img.shields.io/github/contributors/floci-io/floci\" alt=\"GitHub Contributors\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://join.slack.com/t/floci/shared_invite/zt-3tjn02s3q-A00kEjJ1cZxsg_imTfy6Cw\"\u003e\u003cimg src=\"https://img.shields.io/badge/Slack-Join%20the%20community-4A154B?logo=slack\u0026logoColor=white\" alt=\"Join Floci on Slack\"\u003e\u003c/a\u003e\n\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cem\u003eNamed after \u003ca href=\"https://en.wikipedia.org/wiki/Cirrocumulus_floccus\"\u003efloccus\u003c/a\u003e — the cloud formation that looks exactly like popcorn.\u003c/em\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  A free, open-source local AWS emulator. No account. No feature gates. Just\u0026nbsp;\u003ccode\u003edocker compose up\u003c/code\u003e.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Join the community on \u003ca href=\"https://join.slack.com/t/floci/shared_invite/zt-3tjn02s3q-A00kEjJ1cZxsg_imTfy6Cw\"\u003eSlack\u003c/a\u003e to ask questions, share feedback, and discuss Floci with other contributors and users. You can also open any topic in \u003ca href=\"https://github.com/orgs/floci-io/discussions\"\u003eGitHub Discussions\u003c/a\u003e — feature ideas, compatibility questions, design tradeoffs, wild proposals, or half-baked thoughts are all welcome. No idea is too small, too early, or too popcorn-fueled to start a good discussion.\n\u003c/p\u003e\n\n---\n\n\u003e [!IMPORTANT]\n\u003e **Image moved to `floci/floci`.** Update your `docker-compose.yml` and `docker run` commands:\n\u003e ```\n\u003e # Before\n\u003e image: hectorvent/floci:latest\n\u003e # After\n\u003e image: floci/floci:latest\n\u003e ```\n\u003e The old `hectorvent/floci` repository will no longer receive updates.\n\n---\n\n\u003e LocalStack's community edition [sunset in March 2026](https://blog.localstack.cloud/the-road-ahead-for-localstack/) — requiring auth tokens, and freezing security updates. Floci is the no-strings-attached alternative.\n\n## Why Floci?\n\n| | Floci | LocalStack Community |\n|---|---|---|\n| Auth token required | No | Yes (since March 2026) |\n| Security updates | Yes | Frozen |\n| Startup time | **~24 ms** | ~3.3 s |\n| Idle memory | **~13 MiB** | ~143 MiB |\n| Docker image size | **~90 MB** | ~1.0 GB |\n| License | **MIT** | Restricted |\n| API Gateway v2 / HTTP API | ✅ | ❌ |\n| Cognito | ✅ | ❌ |\n| ElastiCache (Redis + IAM auth) | ✅ | ❌ |\n| RDS (PostgreSQL + MySQL + IAM auth) | ✅ | ❌ |\n| MSK (Kafka + Redpanda) | ✅ | ❌ |\n| Athena (real SQL via DuckDB sidecar + Glue views) | ✅ | ❌ |\n| Glue Data Catalog + Schema Registry | ✅ | ❌ |\n| Data Firehose (NDJSON delivery) | ✅ | ❌ |\n| S3 Object Lock (COMPLIANCE / GOVERNANCE) | ✅ | ⚠️ Partial |\n| DynamoDB Streams | ✅ | ⚠️ Partial |\n| IAM (users, roles, policies, groups) | ✅ | ⚠️ Partial |\n| STS (all 7 operations) | ✅ | ⚠️ Partial |\n| Kinesis (streams, shards, fan-out) | ✅ | ⚠️ Partial |\n| KMS (sign, verify, re-encrypt) | ✅ | ⚠️ Partial |\n| ECS (clusters, services, tasks) | ✅ | ❌ |\n| EKS (clusters, mock + real k3s) | ✅ | ❌ |\n| EC2 (real Docker instances, IMDS, SSH, UserData) | ✅ | ❌ |\n| CodeBuild (real Docker build execution, S3 artifacts, CloudWatch logs) | ✅ | ❌ |\n| CodeDeploy (Lambda traffic shifting, lifecycle hooks, auto-rollback) | ✅ | ❌ |\n| Auto Scaling (groups, launch configs, reconciler, ELB v2 integration) | ✅ | ❌ |\n| SSM Run Command (SendCommand + real agent polling via ec2messages) | ✅ | ❌ |\n| Transfer Family (SFTP server management, users, SSH keys) | ✅ | ❌ |\n| Native binary | ✅ ~40 MB | ❌ |\n\n**Broad AWS coverage. Free forever.**\n\n## Migrating from LocalStack\n\nFloci is a drop-in replacement for LocalStack Community. The port (`4566`), credentials, and all AWS SDK and CLI calls work unchanged — swap the image and you're done.\n\n```yaml\n# Before\nimage: localstack/localstack\n\n# After — no init scripts, or scripts that don't call aws / boto3\nimage: floci/floci:latest\n\n# After — init scripts that use aws CLI or boto3\nimage: floci/floci:latest-compat   # includes Python 3, AWS CLI, boto3 pre-configured\n```\n\n**LocalStack environment variables are translated automatically** — no renaming required:\n\n| LocalStack | Floci equivalent |\n|---|---|\n| `LOCALSTACK_HOST` | `FLOCI_HOSTNAME` |\n| `PERSISTENCE=1` | `FLOCI_STORAGE_MODE=persistent` |\n| `LAMBDA_DOCKER_NETWORK` | `FLOCI_SERVICES_LAMBDA_DOCKER_NETWORK` |\n| `LAMBDA_REMOVE_CONTAINERS=1` | `FLOCI_SERVICES_LAMBDA_EPHEMERAL=true` |\n| `DEBUG=1` | `QUARKUS_LOG_LEVEL=DEBUG` |\n\nInit scripts mounted under `/etc/localstack/init/` run unchanged. The `/_localstack/init` and `/_localstack/health` endpoints are still served. Set `LOCALSTACK_PARITY=false` to opt out of the automatic translation.\n\n→ [Full migration guide](https://floci.io/floci/getting-started/migrate-from-localstack/)\n\n## Architecture Overview\n\n```mermaid\nflowchart LR\n    Client[\"☁️ AWS SDK / CLI\"]\n\n    subgraph Floci [\"Floci — port 4566\"]\n        Router[\"HTTP Router\\n(JAX-RS / Vert.x)\"]\n\n        subgraph Stateless [\"Stateless Services\"]\n            A[\"SSM · SQS · SNS\\nIAM · STS · KMS\\nSecrets Manager · SES\\nCognito · Kinesis\\nEventBridge · Scheduler · AppConfig\\nCloudWatch · Step Functions\\nCloudFormation · ACM\\nAPI Gateway · ELB v2 · Auto Scaling\\nCodeDeploy · Backup · Bedrock Runtime · Route53 · Transfer\"]\n        end\n\n        subgraph Stateful [\"Stateful Services\"]\n            B[\"S3 · DynamoDB\\nDynamoDB Streams\"]\n        end\n\n        subgraph Containers [\"Container Services  🐳\"]\n            C[\"Lambda\\nElastiCache\\nRDS\\nECS\\nEC2\\nMSK\\nEKS\\nOpenSearch\\nCodeBuild\"]\n            D[\"Athena ➜ floci-duck\\n(DuckDB sidecar)\"]\n        end\n\n        Router --\u003e Stateless\n        Router --\u003e Stateful\n        Router --\u003e Containers\n        Stateless \u0026 Stateful --\u003e Store[(\"StorageBackend\\nmemory · hybrid\\npersistent · wal\")]\n    end\n\n    Docker[\"🐳 Docker Engine\"]\n    Client --\u003e|\"HTTP :4566\\nAWS wire protocol\"| Router\n    Containers --\u003e|\"Docker API\\n+ IAM / SigV4 auth\"| Docker\n```\n\n## Real Docker Integration\n\nUnlike mock-only emulators, Floci runs **real Docker containers** for services where in-process emulation would compromise fidelity — stateful databases, connection-heavy protocols, and runtimes that require native execution. The result is wire-compatible behavior against the actual engine, not a simplified approximation.\n\n| Service | Default Docker image | What's real |\n|---|---|---|\n| **Lambda** | `public.ecr.aws/lambda/\u003cruntime\u003e` | AWS runtime environment, execution model, warm container pool |\n| **ElastiCache** | `valkey/valkey:8` | Full Redis/Valkey protocol, ACL-based IAM auth, SigV4 validation |\n| **RDS (PostgreSQL)** | `postgres:16-alpine` | Real PostgreSQL engine, IAM auth via token, JDBC-compatible |\n| **RDS (MySQL / Aurora)** | `mysql:8.0` | Real MySQL engine, IAM auth, JDBC-compatible |\n| **RDS (MariaDB)** | `mariadb:11` | Real MariaDB engine, IAM auth, JDBC-compatible |\n| **MSK** | `redpandadata/redpanda:latest` | Real Kafka-compatible broker via Redpanda |\n| **EC2** | AMI-mapped (e.g. `public.ecr.aws/amazonlinux/amazonlinux:2023`) | Real Linux containers; SSH key injection; UserData execution; IMDS with IMDSv1+IMDSv2 and IAM credential serving |\n| **ECS** | User-specified in task definition | Actual container lifecycle — start, stop, health checks |\n| **EKS** | `rancher/k3s:latest` | Live Kubernetes API server (k3s), full kubeconfig |\n| **CodeBuild** | User-specified environment image (e.g. `public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:5.0`) | Real buildspec execution — install/pre_build/build/post_build phases in container; S3 artifact upload; CloudWatch log streaming |\n| **OpenSearch** | `opensearchproject/opensearch:2` | Full OpenSearch engine with REST API |\n| **ECR** | `registry:2` | Real OCI-compatible registry — `docker push` / `docker pull` work natively |\n\n### Lambda runtimes\n\nFloci resolves each Lambda runtime to the corresponding [AWS public ECR image](https://gallery.ecr.aws/lambda):\n\n| Runtime | Image |\n|---|---|\n| `java25` · `java21` · `java17` · `java11` · `java8.al2` · `java8` | `public.ecr.aws/lambda/java:\u003cversion\u003e` |\n| `python3.14` · `python3.13` · `python3.12` · `python3.11` · `python3.10` · `python3.9` | `public.ecr.aws/lambda/python:\u003cversion\u003e` |\n| `nodejs24.x` · `nodejs22.x` · `nodejs20.x` · `nodejs18.x` · `nodejs16.x` | `public.ecr.aws/lambda/nodejs:\u003cversion\u003e` |\n| `ruby3.4` · `ruby3.3` · `ruby3.2` | `public.ecr.aws/lambda/ruby:\u003cversion\u003e` |\n| `dotnet10` · `dotnet9` · `dotnet8` · `dotnet6` | `public.ecr.aws/lambda/dotnet:\u003cversion\u003e` |\n| `go1.x` | `public.ecr.aws/lambda/go:1` |\n| `provided.al2023` · `provided.al2` · `provided` | `public.ecr.aws/lambda/provided:\u003cvariant\u003e` |\n\nContainer image functions (package type `Image`) pass the `ImageUri` through directly, with ECR repository URIs rewritten to the local Floci ECR endpoint automatically.\n\n### Requirements\n\nDocker-backed services require the Docker socket to be accessible:\n\n```bash\ndocker run -d --name floci \\\n  -p 4566:4566 \\\n  -v /var/run/docker.sock:/var/run/docker.sock \\\n  -u root \\\n  floci/floci:latest\n```\n\nIn Docker Compose, add the socket volume alongside any other mounts.\n\n### Overriding default images\n\nAll default images are configurable via environment variables, useful for pinning versions or using a local mirror:\n\n| Variable | Default |\n|---|---|\n| `FLOCI_SERVICES_ELASTICACHE_DEFAULT_IMAGE` | `valkey/valkey:8` |\n| `FLOCI_SERVICES_RDS_DEFAULT_POSTGRES_IMAGE` | `postgres:16-alpine` |\n| `FLOCI_SERVICES_RDS_DEFAULT_MYSQL_IMAGE` | `mysql:8.0` |\n| `FLOCI_SERVICES_RDS_DEFAULT_MARIADB_IMAGE` | `mariadb:11` |\n| `FLOCI_SERVICES_MSK_DEFAULT_IMAGE` | `redpandadata/redpanda:latest` |\n| `FLOCI_SERVICES_OPENSEARCH_DEFAULT_IMAGE` | `opensearchproject/opensearch:2` |\n| `FLOCI_SERVICES_EKS_DEFAULT_IMAGE` | `rancher/k3s:latest` |\n| `FLOCI_SERVICES_ECR_REGISTRY_IMAGE` | `registry:2` |\n| `FLOCI_ECR_BASE_URI` | `public.ecr.aws` (Lambda runtime base) |\n\n## Supported Services\n\n| Service | How it works | Notable features |\n|---|---|---|\n| **SSM Parameter Store** | In-process | Version history, labels, SecureString, tagging |\n| **SSM Run Command** | In-process | `SendCommand`, `GetCommandInvocation`, `ListCommands`, `CancelCommand`; `DescribeInstanceInformation`; `ec2messages` polling protocol so the real `amazon-ssm-agent` running inside EC2 containers can register, receive commands, and report output |\n| **SQS** | In-process | Standard \u0026 FIFO, DLQ, visibility timeout, batch, tagging |\n| **SNS** | In-process | Topics, subscriptions, SQS / Lambda / HTTP delivery, tagging |\n| **S3** | In-process | Versioning, multipart upload, pre-signed URLs, Object Lock, event notifications |\n| **DynamoDB** | In-process | GSI / LSI, Query, Scan, TTL, transactions, batch operations |\n| **DynamoDB Streams** | In-process | Shard iterators, records, Lambda ESM trigger |\n| **Lambda** | **Real Docker containers** | Warm pool, aliases, Function URLs, SQS / Kinesis / DDB Streams ESM |\n| **API Gateway REST** | In-process | Resources, methods, stages, Lambda proxy, MOCK integrations, AWS integrations |\n| **API Gateway v2 (HTTP)** | In-process | Routes, integrations, JWT authorizers, stages |\n| **IAM** | In-process | Users, roles, groups, policies, instance profiles, access keys |\n| **STS** | In-process | AssumeRole, WebIdentity, SAML, GetFederationToken, GetSessionToken |\n| **Cognito** | In-process | User pools, app clients, auth flows, JWKS / OpenID well-known endpoints |\n| **KMS** | In-process | Encrypt / decrypt, sign / verify, data keys, aliases |\n| **Kinesis** | In-process | Streams, shards, enhanced fan-out, split / merge |\n| **Secrets Manager** | In-process | Versioning, resource policies, tagging |\n| **Step Functions** | In-process | ASL execution, task tokens, execution history |\n| **CloudFormation** | In-process | Stacks, change sets, resource provisioning |\n| **EventBridge** | In-process | Custom buses, rules, targets (SQS / SNS / Lambda) |\n| **EventBridge Scheduler** | In-process | Schedule groups, schedules, flexible time windows, retry policies, dead-letter queues |\n| **CloudWatch Logs** | In-process | Log groups, streams, ingestion, filtering |\n| **CloudWatch Metrics** | In-process | Custom metrics, statistics, alarms |\n| **ElastiCache** | **Real Docker containers** | Redis / Valkey, IAM auth, SigV4 validation |\n| **RDS** | **Real Docker containers** | PostgreSQL \u0026 MySQL, IAM auth, JDBC-compatible |\n| **MSK** | **Real Docker containers** | Kafka compatible via Redpanda orchestration |\n| **Athena** | In-process + **DuckDB sidecar** | Real SQL execution; Glue-backed views over S3 data; `read_parquet` / `read_json_auto` / `read_csv_auto` inferred from SerDe |\n| **Glue** | In-process | Data Catalog; Schema Registry for Avro / JSON Schema / Protobuf; tables consumed by Athena as DuckDB views at query time |\n| **Data Firehose** | In-process | Streaming data delivery; records flushed as NDJSON to S3 |\n| **ECS** | **Real Docker containers** | Clusters, task definitions, tasks, services, capacity providers, task sets |\n| **EC2** | **Real Docker containers** | `RunInstances` launches real Docker containers; SSH key injection; UserData execution; IMDS (IMDSv1+IMDSv2, port 9169) with IAM credential serving; VPCs, subnets, security groups, AMIs, key pairs, internet gateways, route tables, Elastic IPs, tags |\n| **ACM** | In-process | Certificate issuance, validation lifecycle |\n| **ECR** | In-process + **real OCI registry** | Repositories, image push / pull via stock `docker`, image-backed Lambda functions |\n| **SES** | In-process | Send email / raw email, identity verification, DKIM attributes, email templates with `{{var}}` substitution |\n| **SES v2 (HTTP)** | In-process | REST JSON API, identities, DKIM, feedback attributes, account sending, email templates with `{{var}}` substitution |\n| **OpenSearch** | **Real Docker containers** | Domain CRUD, tags, versions, instance types, upgrade stubs |\n| **AppConfig** | In-process | Applications, environments, profiles, hosted configuration versions, deployments |\n| **AppConfigData** | In-process | Configuration sessions, dynamic configuration retrieval |\n| **Bedrock Runtime** | In-process (stub) | Dummy Converse and InvokeModel responses for local development; streaming returns 501 |\n| **EKS** | **Real Docker containers** (mock mode available) | Clusters, tagging; real mode starts k3s per cluster with a live Kubernetes API server |\n| **ELB v2** | In-process | Application and Network Load Balancers, target groups, listeners, path/host-based routing rules, Lambda targets (ALB→Lambda event format), tags |\n| **CodeBuild** | In-process + **real Docker containers** | Projects, report groups, source credentials; `StartBuild` runs real Docker containers, streams logs to CloudWatch, uploads artifacts to S3 via `docker cp` (works in Docker-in-Docker) |\n| **CodeDeploy** | In-process + **Lambda traffic shifting** | Applications, deployment groups, deployment configs; 17 `CodeDeployDefault.*` built-ins pre-seeded; `CreateDeployment` shifts Lambda alias `RoutingConfig` weights, invokes lifecycle hooks, auto-rolls back on failure |\n| **Auto Scaling** | In-process + **background reconciler** | Launch configurations, auto scaling groups with min/max/desired capacity; background loop (10 s) calls `RunInstances` / `TerminateInstances` to meet desired capacity; lifecycle hooks, scaling policies, ELB v2 target group auto-registration |\n| **AWS Backup** | In-process | Vaults, backup plans with rules, resource selections, on-demand jobs with simulated lifecycle (CREATED → RUNNING → COMPLETED), recovery points, tagging |\n| **Route53** | In-process | Hosted zones with auto-created SOA + NS records, resource record sets (CREATE/UPSERT/DELETE with atomic validation), change tracking (always INSYNC), health checks, and per-resource tagging |\n| **Transfer Family** | In-process | Server lifecycle (`CreateServer` / `DeleteServer` / `StartServer` / `StopServer` / `UpdateServer`), user management, SSH public key import, and tagging |\n| **Textract** | In-process (stub) | API-compatible stubs for all operations; dummy block data with realistic shape and metadata; async job simulation with immediate SUCCEEDED status |\n\n\u003e **Lambda, ElastiCache, RDS, MSK, ECS, EC2, EKS, OpenSearch, and CodeBuild** spin up real Docker containers and support IAM authentication and SigV4 request signing — the same auth flow as production AWS. **ECR** runs a shared `registry:2` container so the stock `docker` client can push and pull image bytes against repositories returned by the AWS-shaped control plane.\n\u003e\n\u003e For per-service operation counts and endpoint protocols, see the [Services Overview](https://floci.io/floci/services/) in the documentation site.\n\n**46 AWS services supported.**\n\n## Persistence \u0026 Storage Modes\n\nFloci features a flexible storage architecture designed to balance developer productivity, performance, and data durability. You can configure the storage mode globally via `FLOCI_STORAGE_MODE` or override it for specific services.\n\n| Mode | Behavior | Best for... | Durability |\n|:---:|---|---|:---:|\n| **`memory`** | **(Default)** Entirely in-RAM. Data is lost when the container stops. | Speed, ephemeral testing, CI pipelines. | ❌ None |\n| **`persistent`** | Data is loaded at startup and flushed to disk on graceful shutdown. | Simple local dev with state preservation. | ⚠️ Medium |\n| **`hybrid`** | In-memory performance with periodic async flushing (every 5s). | The perfect balance of speed and safety. | ✅ Good |\n| **`wal`** | Write-Ahead Log. Every mutation is logged to disk before responding. | Maximum durability for critical state. | 💎 Highest |\n\n\u003e [!TIP]\n\u003e The default **`memory`** mode is ideal for fast, ephemeral CI pipelines where state doesn't need to survive restarts. Switch to **`hybrid`** for local development when you want state preserved across container restarts without sacrificing performance.\n\nFor more details, visit the [Storage Configuration documentation](https://floci.io/floci/configuration/storage/).\n\n## Multi-Account Isolation\n\nFloci supports full per-account resource isolation with no extra configuration. If your AWS access key ID is **exactly 12 digits**, Floci uses it directly as the account ID — resources created by one account are completely invisible to another.\n\n```bash\n# Two accounts, full isolation — same queue name, separate namespaces\nAWS_ACCESS_KEY_ID=111111111111 aws sqs create-queue --queue-name orders\nAWS_ACCESS_KEY_ID=222222222222 aws sqs create-queue --queue-name orders\n```\n\nAny other key format (e.g. `test`, `AKIA…`) falls back to `FLOCI_DEFAULT_ACCOUNT_ID` (`000000000000` by default) — the standard single-account setup.\n\n→ [Multi-Account Isolation docs](https://floci.io/floci/configuration/multi-account/)\n\n## Quick Start\n\n```yaml\n# docker-compose.yml\nservices:\n  floci:\n    image: floci/floci:latest\n    ports:\n      - \"4566:4566\"\n    volumes:\n      # Local directory bind mount (default)\n      - ./data:/app/data\n      \n      # OR named volume (optional):\n      # - floci-data:/app/data\n\n#volumes:\n#  floci-data:\n```\n\n```bash\ndocker compose up\n```\n\nOr run Floci directly with Docker:\n\n```bash\ndocker run -d --name floci \\\n  -p 4566:4566 \\\n  -v /var/run/docker.sock:/var/run/docker.sock \\\n  -e FLOCI_DEFAULT_REGION=us-east-1 \\\n  -u root \\\n  floci/floci:latest\n```\n\nAll services are available at `http://localhost:4566`. Use any AWS region — credentials can be anything.\n\n```bash\nexport AWS_ENDPOINT_URL=http://localhost:4566\nexport AWS_DEFAULT_REGION=us-east-1\nexport AWS_ACCESS_KEY_ID=test\nexport AWS_SECRET_ACCESS_KEY=test\n\n# Try it\naws s3 mb s3://my-bucket\naws sqs create-queue --queue-name my-queue\naws dynamodb list-tables\n```\n\n## SDK Integration\n\nPoint your existing AWS SDK at `http://localhost:4566` — no other changes needed.\n\n```java\n// Java (AWS SDK v2)\nvar client = DynamoDbClient.builder()\n    .endpointOverride(URI.create(\"http://localhost:4566\"))\n    .region(Region.US_EAST_1)\n    .credentialsProvider(StaticCredentialsProvider.create(\n        AwsBasicCredentials.create(\"test\", \"test\")))\n    .build();\n\nclient.createTable(b -\u003e b\n    .tableName(\"demo-table\")\n    .billingMode(BillingMode.PAY_PER_REQUEST)\n    .attributeDefinitions(\n        AttributeDefinition.builder().attributeName(\"pk\").attributeType(ScalarAttributeType.S).build())\n    .keySchema(\n        KeySchemaElement.builder().attributeName(\"pk\").keyType(KeyType.HASH).build()));\n\nclient.putItem(b -\u003e b\n    .tableName(\"demo-table\")\n    .item(Map.of(\"pk\", AttributeValue.fromS(\"item-1\"))));\n\nSystem.out.println(client.listTables().tableNames());\n```\n\n```python\n# Python (boto3)\nimport boto3\nclient = boto3.client(\"ssm\",\n    endpoint_url=\"http://localhost:4566\",\n    region_name=\"us-east-1\",\n    aws_access_key_id=\"test\",\n    aws_secret_access_key=\"test\")\n\nclient.put_parameter(\n    Name=\"/demo/app/message\",\n    Value=\"hello from floci\",\n    Type=\"String\",\n    Overwrite=True,\n)\n\nresponse = client.get_parameter(Name=\"/demo/app/message\")\nprint(response[\"Parameter\"][\"Value\"])\n```\n\n```javascript\n// consumer.mjs\n// Node.js (AWS SDK v3)\nimport {DeleteMessageCommand, ReceiveMessageCommand, SQSClient,} from \"@aws-sdk/client-sqs\";\n\nconst client = new SQSClient({\n    endpoint: \"http://localhost:4566\",\n    region: \"us-east-1\",\n    credentials: {accessKeyId: \"test\", secretAccessKey: \"test\"},\n});\n\nconst QUEUE_URL = \"http://localhost:4566/000000000000/demo-queue\";\n\nconst response = await client.send(\n    new ReceiveMessageCommand({\n        QueueUrl: QUEUE_URL,\n        MaxNumberOfMessages: 1,\n        WaitTimeSeconds: 5,\n    }),\n);\n\nif (response.Messages) {\n    for (const msg of response.Messages) {\n        console.log(\"Message received:\", msg.Body);\n\n        await client.send(\n            new DeleteMessageCommand({\n                QueueUrl: QUEUE_URL,\n                ReceiptHandle: msg.ReceiptHandle,\n            }),\n        );\n    }\n}\n\n```\n```javascript\n// producer.mjs\n// Node.js (AWS SDK v3)\nimport {SendMessageCommand, SQSClient} from \"@aws-sdk/client-sqs\";\n\nconst client = new SQSClient({\n    endpoint: \"http://localhost:4566\",\n    region: \"us-east-1\",\n    credentials: {accessKeyId: \"test\", secretAccessKey: \"test\"},\n});\n\nconst QUEUE_URL = \"http://localhost:4566/000000000000/demo-queue\";\n\nawait client.send(\n    new SendMessageCommand({\n        QueueUrl: QUEUE_URL,\n        MessageBody: \"hello from producer\",\n    }),\n);\n\nconsole.log(\"Message sent\");\n\n```\n\n```go\n// Go (AWS SDK v2)\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"strings\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\t\"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/aws/aws-sdk-go-v2/credentials\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3\"\n)\n\nfunc main() {\n\tcfg, err := config.LoadDefaultConfig(context.TODO(),\n\t\tconfig.WithRegion(\"us-east-1\"),\n\t\tconfig.WithCredentialsProvider(\n\t\t\tcredentials.NewStaticCredentialsProvider(\"test\", \"test\", \"\"),\n\t\t),\n\t\tconfig.WithBaseEndpoint(\"http://localhost:4566\"),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tclient := s3.NewFromConfig(cfg, func(o *s3.Options) {\n\t\to.UsePathStyle = true\n\t})\n\n\t_, err = client.CreateBucket(context.TODO(), \u0026s3.CreateBucketInput{\n\t\tBucket: aws.String(\"demo-bucket\"),\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t_, err = client.PutObject(context.TODO(), \u0026s3.PutObjectInput{\n\t\tBucket: aws.String(\"demo-bucket\"),\n\t\tKey:    aws.String(\"demo.txt\"),\n\t\tBody:   strings.NewReader(\"hello from floci\"),\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tout, err := client.ListObjectsV2(context.TODO(), \u0026s3.ListObjectsV2Input{\n\t\tBucket: aws.String(\"demo-bucket\"),\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif len(out.Contents) \u003e 0 {\n\t\tfmt.Println(*out.Contents[0].Key)\n\t}\n}\n\n```\n\n```rust\n// Rust (AWS SDK)\nuse aws_sdk_secretsmanager::config::{Credentials, Region};\nuse aws_sdk_secretsmanager::Client;\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n    let config = aws_config::defaults(aws_config::BehaviorVersion::latest())\n        .region(Region::new(\"us-east-1\"))\n        .credentials_provider(Credentials::new(\"test\", \"test\", None, None, \"floci\"))\n        .endpoint_url(\"http://localhost:4566\")\n        .load()\n        .await;\n\n    let client = Client::new(\u0026config);\n\n    client\n        .create_secret()\n        .name(\"demo/secret\")\n        .secret_string(\"hello from floci\")\n        .send()\n        .await?;\n\n    let secret = client\n        .get_secret_value()\n        .secret_id(\"demo/secret\")\n        .send()\n        .await?;\n\n    println!(\"{}\", secret.secret_string().unwrap());\n\n    Ok(())\n}\n```\n\n```bash\n# Bash (AWS CLI)\nexport AWS_ACCESS_KEY_ID=test\nexport AWS_SECRET_ACCESS_KEY=test\nexport AWS_DEFAULT_REGION=us-east-1\n\ntmp_file=\"$(mktemp)\"\necho \"hello from floci\" \u003e \"$tmp_file\"\n\naws --endpoint-url http://localhost:4566 s3 mb s3://my-bucket\naws --endpoint-url http://localhost:4566 s3 cp \"$tmp_file\" s3://my-bucket/demo.txt\naws --endpoint-url http://localhost:4566 s3 ls s3://my-bucket\n\n# Cleanup\naws --endpoint-url http://localhost:4566 s3 rm s3://my-bucket/demo.txt\nrm -f \"$tmp_file\"\n```\n\n## Testcontainers\n\nFloci has first-class Testcontainers modules so you can start a real Floci instance from your tests with zero manual setup — no running daemon, no shared state, no port conflicts.\n\n| Language | Package | Latest | Registry | Source |\n|---|---|---|---|---|\n| Java | `io.floci:testcontainers-floci` | `1.4.0` | [Maven Central](https://mvnrepository.com/artifact/io.floci/testcontainers-floci) | [GitHub](https://github.com/floci-io/testcontainers-floci) |\n| Node.js | `@floci/testcontainers` | `0.1.0` | [npm](https://www.npmjs.com/package/@floci/testcontainers) | [GitHub](https://github.com/floci-io/testcontainers-floci-node) |\n| Python | `testcontainers-floci` | `0.1.1` | [PyPI](https://pypi.org/project/testcontainers-floci/) | [GitHub](https://github.com/floci-io/testcontainers-floci-python) |\n| Go | — | 🚧 In progress | — | [GitHub](https://github.com/floci-io/testcontainers-floci-go) |\n\n### Java\n\nAdd the dependency (Testcontainers 1.x / Spring Boot 3.x):\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.floci\u003c/groupId\u003e\n    \u003cartifactId\u003etestcontainers-floci\u003c/artifactId\u003e\n    \u003cversion\u003e1.4.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\nFor Testcontainers 2.x / Spring Boot 4.x use version `2.5.0`.\n\nBasic usage with JUnit 5:\n\n```java\n@Testcontainers\nclass S3IntegrationTest {\n\n    @Container\n    static FlociContainer floci = new FlociContainer();\n\n    @Test\n    void shouldCreateBucket() {\n        S3Client s3 = S3Client.builder()\n                .endpointOverride(URI.create(floci.getEndpoint()))\n                .region(Region.of(floci.getRegion()))\n                .credentialsProvider(StaticCredentialsProvider.create(\n                        AwsBasicCredentials.create(floci.getAccessKey(), floci.getSecretKey())))\n                .forcePathStyle(true)\n                .build();\n\n        s3.createBucket(b -\u003e b.bucket(\"my-bucket\"));\n\n        assertThat(s3.listBuckets().buckets())\n                .anyMatch(b -\u003e b.name().equals(\"my-bucket\"));\n    }\n}\n```\n\n**Spring Boot** — add `spring-boot-testcontainers-floci` and use `@ServiceConnection` for zero-config auto-wiring:\n\n```java\n@SpringBootTest\n@Testcontainers\nclass AppIntegrationTest {\n\n    @Container\n    @ServiceConnection\n    static FlociContainer floci = new FlociContainer();\n\n    @Autowired\n    S3Client s3;\n\n    @Test\n    void shouldCreateBucket() {\n        s3.createBucket(b -\u003e b.bucket(\"my-bucket\"));\n        assertThat(s3.listBuckets().buckets())\n                .anyMatch(b -\u003e b.name().equals(\"my-bucket\"));\n    }\n}\n```\n\n### Node.js / TypeScript\n\n```sh\nnpm install --save-dev @floci/testcontainers\n```\n\n```ts\nimport { FlociContainer } from \"@floci/testcontainers\";\nimport { S3Client, CreateBucketCommand, ListBucketsCommand } from \"@aws-sdk/client-s3\";\n\ndescribe(\"S3\", () =\u003e {\n    let floci: FlociContainer;\n\n    beforeAll(async () =\u003e {\n        floci = await new FlociContainer().start();\n    });\n\n    afterAll(async () =\u003e {\n        await floci.stop();\n    });\n\n    it(\"should create and list a bucket\", async () =\u003e {\n        const s3 = new S3Client({\n            endpoint: floci.getEndpoint(),\n            region: floci.getRegion(),\n            credentials: {\n                accessKeyId: floci.getAccessKey(),\n                secretAccessKey: floci.getSecretKey(),\n            },\n            forcePathStyle: true,\n        });\n\n        await s3.send(new CreateBucketCommand({ Bucket: \"my-bucket\" }));\n        const { Buckets } = await s3.send(new ListBucketsCommand({}));\n        expect(Buckets?.some(b =\u003e b.Name === \"my-bucket\")).toBe(true);\n    });\n});\n```\n\n### Python\n\n```sh\npip install testcontainers-floci\n```\n\n```python\nimport boto3\nfrom testcontainers_floci import FlociContainer\n\ndef test_s3_create_bucket():\n    with FlociContainer() as floci:\n        s3 = boto3.client(\n            \"s3\",\n            endpoint_url=floci.get_endpoint(),\n            region_name=floci.get_region(),\n            aws_access_key_id=floci.get_access_key(),\n            aws_secret_access_key=floci.get_secret_key(),\n        )\n\n        s3.create_bucket(Bucket=\"my-bucket\")\n        buckets = s3.list_buckets()[\"Buckets\"]\n        assert any(b[\"Name\"] == \"my-bucket\" for b in buckets)\n```\n\nPytest fixture style:\n\n```python\nimport pytest\nimport boto3\nfrom testcontainers_floci import FlociContainer\n\n@pytest.fixture(scope=\"session\")\ndef floci():\n    with FlociContainer() as container:\n        yield container\n\ndef test_s3_create_bucket(floci):\n    s3 = boto3.client(\n        \"s3\",\n        endpoint_url=floci.get_endpoint(),\n        region_name=floci.get_region(),\n        aws_access_key_id=floci.get_access_key(),\n        aws_secret_access_key=floci.get_secret_key(),\n    )\n    s3.create_bucket(Bucket=\"my-bucket\")\n    buckets = s3.list_buckets()[\"Buckets\"]\n    assert any(b[\"Name\"] == \"my-bucket\" for b in buckets)\n```\n\n### Go\n\nGo support is in progress. Track it at [testcontainers-floci-go](https://github.com/floci-io/testcontainers-floci-go).\n\n## Compatibility Testing\n\n\u003e For full compatibility validation against real SDK and client workflows, see the [compatibility-tests](./compatibility-tests/) directory.\n\nThis directory provides a dedicated compatibility test suite for Floci across multiple SDKs and tooling scenarios, and is the recommended starting point when verifying integration behavior end to end.\n\nAvailable compatibility test modules:\n\n| Module | Language / Tool | SDK / Client / Version | Tests |\n|---|---|---|---:|\n| `sdk-test-java` | Java 17 | AWS SDK for Java v2 | 889 |\n| `sdk-test-node` | Node.js | AWS SDK for JavaScript v3 | 360 |\n| `sdk-test-python` | Python 3 | boto3 | 264 |\n| `sdk-test-go` | Go | AWS SDK for Go v2 | 136 |\n| `sdk-test-awscli` | Bash | AWS CLI v2 | 145 |\n| `sdk-test-rust` | Rust | AWS SDK for Rust | 86 |\n| `compat-terraform` | Terraform | v1.10+ | 14 |\n| `compat-opentofu` | OpenTofu | v1.9+ | 14 |\n| `compat-cdk` | AWS CDK | v2+ | 17 |\n\n**1,850+ automated compatibility tests across 6 SDKs and 3 IaC tools.**\n\n## Image Tags\n\nEvery tag combines two choices: **variant** (what's inside) and **channel** (how stable).\n\n|  | Standard | Compat (+ AWS CLI + boto3) |\n|---|---|---|\n| **Release (latest)** | `latest` ✅ | `latest-compat` |\n| **Release (pinned)** | `x.y.z` | `x.y.z-compat` |\n| **Nightly (floating)** | `nightly` | `nightly-compat` |\n| **Nightly (dated)** | `nightly-mmddyyyy` | `nightly-mmddyyyy-compat` |\n\n- **Standard** — GraalVM native binary. ~24 ms startup, ~40 MB image, ~13 MiB idle memory.\n- **Compat** — Extends the standard image with Python 3, AWS CLI, and boto3. Same startup and memory, larger image.\n- **Release** — Published on every stable version tag.\n- **Nightly** — Built every night at 22:00 CT from `main`. Dated tags (e.g. `nightly-05022026`) are fixed; `nightly` always points to the latest.\n\n```yaml\n# Recommended\nimage: floci/floci:latest\n\n# With AWS CLI + boto3\nimage: floci/floci:latest-compat\n\n# Pinned\nimage: floci/floci:1.5.11\n\n# Track main\nimage: floci/floci:nightly\n```\n\n## Configuration\n\nAll settings are overridable via environment variables (`FLOCI_` prefix).\n\n| Variable | Default | Description                                                                         |\n|---|---|-------------------------------------------------------------------------------------|\n| `FLOCI_PORT` | `4566` | Port exposed by the Floci API                                                       |\n| `FLOCI_DEFAULT_REGION` | `us-east-1` | Default AWS region                                                                  |\n| `FLOCI_DEFAULT_ACCOUNT_ID` | `000000000000` | Default AWS account ID                                                              |\n| `FLOCI_BASE_URL` | `http://localhost:4566` | Base URL used when Floci returns service URLs (e.g. SQS QueueUrl)                   |\n| `FLOCI_HOSTNAME` | *(unset)* | Hostname to use in returned URLs when Floci runs inside Docker Compose              |\n| `FLOCI_STORAGE_MODE` | `memory` | Controls how data is stored across runs: `memory` · `persistent` · `hybrid` · `wal` |\n| `FLOCI_STORAGE_PERSISTENT_PATH` | `./data` | Directory used for persisted state                                                  |\n| `FLOCI_ECR_BASE_URI` | `public.ecr.aws` | AWS ECR base URI used when pulling container images (e.g. Lambda)                   |\n\n* Full reference: [configuration docs](https://floci.io/floci/configuration/application-yml/)\n* Per-service storage overrides: [storage docs](https://floci.io/floci/configuration/storage/#per-service-storage-overrides)\n\n**Multi-container Docker Compose:** When your application runs in a separate container from Floci, set `FLOCI_HOSTNAME` to the Floci service name so that returned URLs (e.g. SQS QueueUrl) resolve correctly:\n\n```yaml\nservices:\n  floci:\n    image: floci/floci:latest\n    ports:\n      - \"4566:4566\"\n    environment:\n      - FLOCI_HOSTNAME=floci  # URLs will use http://floci:4566/...\n  my-app:\n    environment:\n      - AWS_ENDPOINT_URL=http://floci:4566\n    depends_on:\n      - floci\n```\n\nWithout this, SQS returns `http://localhost:4566/...` in QueueUrl responses, which resolves to the wrong container.\n\n## Star history\n\n[![Star History Chart](https://api.star-history.com/svg?repos=floci-io/floci\u0026type=Date)](https://star-history.com/#floci-io/floci\u0026Date)\n\n## Contributors\n\n\u003ca href=\"https://github.com/floci-io/floci/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=floci-io/floci\" /\u003e\n\u003c/a\u003e\n\n## License\n\nMIT — use it however you want.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffloci-io%2Ffloci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffloci-io%2Ffloci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffloci-io%2Ffloci/lists"}