Alternatives for LocalStack in TestContainers with Spring Boot
Introduction
Since around 20 March 2026 the company behind LocalStack decided to not support the community edition of LocalStack anymore, only paid versions are now available.
A lot of forks were made from that now-frozen community repository, like this one. Will any of these become the new community supported version?
Many teams use LocalStack within TestContainers in a Spring Boot application for example. What are the alternatives? This post is about exploring those.
Note that you can also pin the version of LocalStack to the last community edition release 4.14.0, that will keep on working after 6 april 2026. But there won’t be any updates on it of course…
Two forms are emerging: either replace the whole AWS stack as much as possible with one framework, or take an separate implementation per AWS service, so: implementation A to support one specific AWS service and implementation B for another AWS service, etc.
Below I’ve split my analysis in those two forms.
Full AWS stack replacements
Several options exist for full AWS stack replacements.
Floci
Floci is a free, open-source local AWS emulator which can be found at https://github.com/floci-io/floci
It is a very recently created project , but got quite some traction already.
A week ago Floci changed into a separate organisation, see this LinkedIn post
It is not a ful drop-in replacement in TestContainers, but it comes close. Below shows what needs changing in a Kotlin Spring Boot application if you are currently using LocalStack.
Replacing LocalStack
You probably have something like this currently configured with LocalStack:
@TestConfiguration
class TestConfig {
@Bean
fun localStackContainer(): LocalStackContainer {
return LocalStackContainer(DockerImageName.parse("localstack/localstack:4:14:0"))
.withServices(LocalStackContainer.Service.DYNAMODB)
}
Basically changing it by replacing the docker image name and the environment variables should get it working already you’d think, so like this:
@TestConfiguration
class TestConfig {
@Bean
fun localStackContainer(): LocalStackContainer {
return LocalStackContainer(DockerImageName.parse(hectorvent/floci:1.5.2).asCompatibleSubstituteFor("localstack/localstack"))
.withEnv("AWS_ENDPOINT_URL", "http://localhost:4566")
.withEnv("AWS_DEFAULT_REGION", "us-east-1")
.withEnv("AWS_ACCESS_KEY_ID", "test")
.withEnv("AWS_SECRET_ACCESS_KEY", "test")
}
But no it is not that easy. You’ll need to insert a different startup-script.
For example like this:
class FlociContainer(dockerImageName: DockerImageName) : LocalStackContainer(dockerImageName) {
override fun containerIsStarting(containerInfo: InspectContainerResponse) {
var shell: String
var executable: String
if (dockerImageName.contains("jvm")) {
shell = "/bin/sh"
executable = "java -jar quarkus-app/quarkus-run.jar"
} else {
shell = "/bin/bash"
executable = "./application"
}
var command = shell + "\n" + executable + "\n"
try {
copyFileToContainer(Transferable.of(command, 511), STARTER_SCRIPT)
} catch (e: Throwable) {
logger.error("Failed to copy startup script to container: ${e.message}", e)
throw e
}
}
…
}
Note the logic to determine the correct command for the startup-script to use in the Docker image. Floci has a native version which has a different startup-script than the JVM version.
You’ll also need to parse for a different startup string than LocalStack has.
TestContainers has a module for LocalStack that looks for this string: ".*Ready\\.\n"
But Floci does not log that string, so one to search for is: ".*started in.*"
So you need to override that for the Floci version.
Then the test configuration becomes this:
@TestConfiguration
class TestConfig {
@Bean
fun localStackContainer(): LocalStackContainer {
val flociImage: DockerImageName =
DockerImageName.parse(hectorvent/floci:1.5.2).asCompatibleSubstituteFor("localstack/localstack")
return FlociContainer(flociImage)
// Floci settings
.withEnv("AWS_ENDPOINT_URL", "http://localhost:4566")
.withEnv("AWS_DEFAULT_REGION", "us-east-1")
.withEnv("AWS_ACCESS_KEY_ID", "test")
.withEnv("AWS_SECRET_ACCESS_KEY", "test")
// Disable services you don’t need
.withEnv("FLOCI_SERVICES_SSM_ENABLED", "false")
.withEnv("FLOCI_SERVICES_ELASTICSEARCH_ENABLED", "false")
// Floci container has different log-text to look for
.waitingFor(LogMessageWaitStrategy().withRegEx(".*started in.*").withTimes(1))
}
That should do it!
Building Docker JVM image of Floci and start it locally
For building a Docker image for the JVM version, you can run these commands in the root directory of the Floci project:
- Create the artifact (application) for the Docker image: ./mvnw clean package
- Build the docker image: docker build . -t floci-jvm-package:1.5.1-fix-001 -f Dockerfile.jvm-package
To start the JVM image of Floci locally you can run this command in the root directory:
docker-compose -f docker-compose-fix-001.xml up
With this in that docker compose file:
services:
floci:
image: floci-jvm-package:1.5.1-fix-001
ports:
- "4566:4566"
volumes:
- ./data:/app/data
- ./init/start.d:/etc/floci/init/start.d:ro
- ./init/stop.d:/etc/floci/init/stop.d:ro
The output will look something like this then:
✔ Container common-adapters-floci-1 Recreated 0.1s
Attaching to floci-1
floci-1 | ______ _ ____ _____ _____
floci-1 | | ____| | / __ \ / ____|_ _|
floci-1 | | |__ | | | | | | | | |
floci-1 | | __| | | | | | | | | |
floci-1 | | | | |___| |__| | |____ _| |_
floci-1 | |_| |______\____/ \_____|_____|
floci-1 |
floci-1 |
floci-1 | Powered by Quarkus 3.32.3
floci-1 | 2026-04-11 15:51:14,012 INFO [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) === AWS Local Emulator Starting ===
floci-1 | 2026-04-11 15:51:14,012 INFO [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) Storage mode: memory
floci-1 | 2026-04-11 15:51:14,012 INFO [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) Persistent path: ./data
floci-1 | 2026-04-11 15:51:14,012 INFO [io.github.hectorvent.floci.core.common.ServiceRegistry] (main) Enabled services: [ssm, sqs, s3, dynamodb, sns, lambda, apigateway, iam, elasticache, rds, events, scheduler, logs, monitoring, secretsmanager, apigatewayv2, kinesis, kms, cognito-idp, states, cloudformation, acm, email, es]
floci-1 | 2026-04-11 15:51:14,013 INFO [io.github.hectorvent.floci.lifecycle.EmulatorLifecycle] (main) === AWS Local Emulator Ready ===
floci-1 | 2026-04-11 15:51:14,021 INFO [io.quarkus] (main) floci 1.4.0 native (powered by Quarkus 3.32.3) started in 0.085s. Listening on: http://0.0.0.0:4566
floci-1 | 2026-04-11 15:51:14,021 INFO [io.quarkus] (main) Profile prod activated.
floci-1 | 2026-04-11 15:51:14,021 INFO [io.quarkus] (main) Installed features: [cdi, config-yaml, rest, rest-jackson, smallrye-context-propagation, vertx]
Notice also the ‘started in 0.085s’, which contains the string for which the above example FlociContainer is looking for to see if the container started successfully.
Automatically create your application queues in Floci
A fancy enhancement for when you are using Spring Boot: you can write a BeanFactoryPostProcessor which parses for @SqsListener annotations to automatically create the queues in the Floci container.
Run Integration Tests against locally running Floci
To run your tests against a locally running Floci instance directly, for example to see its logging, started up with Docker like mentioned above, you override the endpoint when creating the DynamoDBClient:
return DynamoDbClient.builder()
.endpointOverride(URI.create("http://localhost:4566"))
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(localStackContainer.accessKey, localStackContainer.secretKey)))
.region(Region.of(localStackContainer.region))
.build()
}
Testcontainers module for Floci
There’s now also a testcontainers module available for floci so you should not need all above manual changes: https://testcontainers.com/modules/floci/
I did not test this module yet.
Other full replacement options
- Rust focused it seems: Rustack
- Only 1 maintainer and runs standalone, some AWS, some GCP, some Azure services supported: CloudTwin
- Python focused it seems: Moto: This post talks about Moto mocking and using it in unittests. Is it a mocking or emulating framework?
- Any of the LocalStack forks.
AWS stack per-service replacement
Multiple options exist, this list might not be listing all options.
- DynamoDB:
- use the AWS DynamoDB Local replacement. Docker image is here. Can be used on its own, and there’s a TestContainers module for it too here.
- Dynalite: last update in 2020, seems to be dead. The TestContainers module seems to be gone now too
- S3: Minio Not supported anymore, see here.
- SQS: https://lib.rs/crates/tc_elasticmq. Docker image here.

Digg
No comments:
Post a Comment