gofakes3 gives your tests a local S3 without touching AWS
A simple fake AWS S3 object storage (used for local test-runs against AWS S3 APIs)
At a glance
- What is it?
- gofakes3 is a Go implementation of an AWS S3 server meant for local development and integration tests, with an in-memory backend and a fake server you can start in the same process as your test. The project is explicit that it is a development tool, that large parts of the S3 API are still missing, and that breaking changes are expected.
- Who is it for?
- gofakes3 is a good fit for Go teams testing code that talks to S3 without an AWS account, in particular Lambda handlers and SDK clients, because it starts inside the test process and needs no container or credentials. It is the wrong choice for anything touching real data, since the README says it has no demand for correctness, performance or security.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A fake S3 for tests that would otherwise need an AWS account
The problem gofakes3 solves is narrow and common. You are writing a service that reads or writes objects in S3, you want tests that run on a laptop and in CI without credentials or network calls, and you do not want to mock the SDK. The project describes itself as an AWS S3 fake server and testing library for comprehensive S3 integration testing.
The README lists three intended uses. The first is local development of S3-dependent AWS Lambda functions. The second is testing implementations with AWS S3 access. The third is facilitating browser-based direct uploads to S3 in a local testing environment, which is the case the upload example in the documentation covers with a form posting to the local endpoint.
Two audiences are explicitly excluded. The first is production use of any kind. The second is anyone who needs the full S3 API surface, because the README states that the tool is still under development with significant portions of the AWS S3 API yet to be implemented, and that breaking changes are expected as a consequence. The project also says plainly that it is used internally and for local development only, so it has no demand for correctness, performance or security.
The backend is pluggable, and the Docker image ships the memory one
The fake server is split into a routing layer and a backend, and the Docker image in the repository makes the split visible.
FROM scratch
ADD ca-certificates.crt /etc/ssl/certs/
ADD build/main /
EXPOSE 9000
CMD ["/main", "-backend", "mem"]The entrypoint takes a backend argument, and the shipped default is mem. The image is built from scratch with only the CA certificate bundle and the compiled binary added, and it listens on port 9000.
The Go module lists the storage engines it builds on. It requires go.etcd.io/bbolt, gopkg.in/mgo.v2, github.com/spf13/afero and github.com/ryszard/goskiplist alongside the AWS SDK for Go v2 packages, which points to a design where the same HTTP behaviour can sit on top of memory, file and embedded key-value stores. The example in the README uses the in-memory backend directly, s3mem, which is the simplest option for a test that throws its data away afterwards.
That pluggability is the interesting part of the design for a fake. The same routing code, the chunked upload handling, the range requests and the CORS handling serve whichever backend you plug in, so a team can run a fast in-memory fake in unit tests and a persistent one for a longer integration session.
Path-style addressing avoids the hosts file, and that is the point
S3 has two addressing styles and the difference decides how much setup a test needs. In path-style the bucket name is part of the URL path, at http://localhost:9000/mybucket/myobject for example. In virtual-hosted style the bucket name moves into the hostname, at http://mybucket.localhost:9000/myobject, which requires DNS configuration and, as the README notes, an entry in /etc/hosts for every bucket you want to use.
The README recommends path-style, calling it the most flexible and least restrictive approach, and the Go SDK v2 needs it switched on explicitly.
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.UsePathStyle = true
})The third option is the environment variable, which matters when the S3 client is created somewhere you do not control.
os.Setenv("AWS_ENDPOINT_URL_S3", "http://localhost:9000")For JavaScript the equivalent is a client option. The README's AWS SDK v3 for JavaScript example sets the endpoint and turns on path style explicitly, noting in a comment that it is required for gofakes3, while the legacy AWS SDK v2 example uses s3ForcePathStyle and describes that flag as recommended rather than required. The difference between required and recommended is worth noticing: a v3 client without forcePathStyle will try virtual-hosted addressing and fail against a local server that has no wildcard DNS.
Starting the fake inside the test process with httptest
The most useful integration mode does not need Docker at all. The README's Go example creates the backend, wraps it in the fake server, and hands it to httptest.NewServer, so the whole thing lives inside the test binary and shuts down with it.
backend := s3mem.New()
faker := gofakes3.New(backend)
ts := httptest.NewServer(faker.Server())From there the fake is an ordinary HTTP server, and the AWS SDK v2 client points at it through an endpoint resolver and static credentials. The example creates a bucket named newbucket and puts an object called test.txt into it, and the comment after that says that accessing test.txt through any S3 client would now be possible.
Two details in that example are worth copying. The client is built with o.UsePathStyle set to true, and the static credentials provider is filled with ACCESS_KEY and SECRET_KEY. The fake accepts those values without checking them against anything, which is exactly what a test fixture wants and exactly why the project states it is not for production.
The repository also ships a dedicated example directory with client.go, main.go and server.go, so a standalone server and a client example exist alongside the in-process pattern.
What the API surface is missing, and why that matters for your tests
The incomplete API is the real constraint, and the README is upfront about it. Significant portions of the AWS S3 API are yet to be implemented, and the project expects breaking changes while that work continues.
The source layout gives a hint of how far along it is. The repository root is a set of single-purpose files, including chunk.go for multipart handling, range.go for range requests, prefix.go for prefix listing, uploader.go, hash.go, cors.go, validation.go, routing.go and option.go, plus an internal directory and a backend directory. The presence of cors.go and validation.go indicates that browser uploads and request validation are handled at all, and the multipart form example in the README posts fields such as acl, x-amz-meta-uuid and x-amz-server-side-encryption to the local endpoint, so presigned-post style uploads are part of the intent.
The failure mode for a new user is quiet. A test that exercises an unimplemented operation does not fail loudly at setup time, it fails when the code path is first hit, often in a test you did not expect to be affected. The mitigation is boring: check the operations your code actually calls against what the fake implements before you rely on the suite, and treat a green run as evidence about the paths that were exercised rather than about S3 compatibility.
gofakes3 against a real bucket and against a filesystem abstraction
There are two realistic alternatives, and they differ in what they preserve. The first is a real S3 bucket or a containerised S3 service, which preserves the actual API behaviour and the actual network path at the cost of credentials, network calls and cleanup. The second is skipping S3 entirely in tests and stubbing the filesystem, which the module's dependency on github.com/spf13/afero suggests is a familiar pattern in Go projects.
gofakes3 sits between the two. It keeps the HTTP surface of S3, so your SDK code path is unchanged and the test exercises request signing, addressing style, error shapes and response parsing. It drops the durability and the fidelity, so it cannot tell you that your bucket policy is wrong or that a lifecycle rule behaves as you expected.
The README points to a Similar Notable Projects section for established alternatives for production, which is the right pointer if you are evaluating this for anything other than a test suite.
MIT licensed, moving through minor versions, built on Go 1.24
gofakes3 is released under the MIT licence, with the licence text in the LICENSE file at the repository root. The module targets Go 1.24 with toolchain go1.24.2, so a project on an older Go line will need to upgrade or pin an earlier release.
The release history shows the sort of churn the README warns about. Version 1.2.0 and version 1.1.0 were both published on 2026-07-09, about forty minutes apart, and 1.0.0 came on 2025-09-16. The default branch is master rather than main. The last push to the repository was on 2026-10-11, so the code is still moving.
For an MIT licensed project used only inside test suites, the licence question is simple: you can vendor it, modify it and keep it inside a proprietary codebase, provided the notice travels with it. The operational question is less simple. Because breaking changes are expected and versions move within a day, pin the version in your go.mod and read the release notes before bumping it, rather than tracking the default branch.
Editorial conclusion
gofakes3 is a good fit for Go teams testing code that talks to S3 without an AWS account, in particular Lambda handlers and SDK clients, because it starts inside the test process and needs no container or credentials. It is the wrong choice for anything touching real data, since the README says it has no demand for correctness, performance or security. Verify first which S3 operations your code actually calls, since the README states that significant portions of the AWS S3 API are yet to be implemented, then pin the version you use because breaking changes are expected.
Frequently asked questions
How do I install gofakes3?
The README documents two ways: pull the Docker image with docker pull johannesboyne/gofakes3, or add the module to a Go project with go get github.com/johannesboyne/gofakes3. The repository also contains an example directory showing a standalone server and a client.
Can I use gofakes3 in production?
No. The README says it should not be used as a production service, that it is not designed for production-level data storage, and that it is used internally and for local development only, with no demand for correctness, performance or security.
Why does my S3 client fail against gofakes3 with a DNS error?
The client is probably using virtual-hosted addressing, where the bucket name is part of the hostname, which needs DNS configuration or an /etc/hosts entry. The README recommends path-style addressing, which in AWS SDK v2 means setting o.UsePathStyle = true, and in the JavaScript SDK v3 means setting forcePathStyle.
Which Go version and Docker setup does gofakes3 use?
The module targets Go 1.24 with toolchain go1.24.2. The Docker image is built FROM scratch, adds the CA certificate bundle and the compiled binary, exposes port 9000 and starts /main with the -backend mem argument.
Is the whole AWS S3 API implemented in gofakes3?
No. The README states that the tool is still under development with significant portions of the AWS S3 API yet to be implemented, and that breaking changes are expected. Check that the operations your code calls are supported before relying on a green test run.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/johannesboyne-gofakes3)Was this useful?