On November 11, 2026 (US time), AWS released AWS Emulator. It is a tool that receives your AWS SDK and AWS CLI calls on your own machine instead of in the cloud, and answers them with the same shape of response that AWS would return.
When I saw the announcement, the first thing that came to mind was this:
Do the AWS Blocks mocks still have a reason to exist?
I have been making small contributions to AWS Blocks since it entered public preview. In a previous post, I looked at how Blocks differs from Amplify and App Studio.
One of the defining features of Blocks is that npm run dev runs the whole application on your machine without an AWS account. That works because every Block ships its own local implementation, in other words a mock. Now AWS itself has released a tool that reproduces AWS locally, so I wanted to know whether the two collide or fit together.
This post looks at the source code of both repositories, the raw data behind the fidelity scores that AWS Emulator publishes, and the results of running the same operations against the Blocks mocks and against AWS Emulator. It is one user and contributor's reading, not an official AWS position or roadmap.
The short answer: not a replacement, but a third layer
Here is where things stand today.
- The two tools replace AWS at different layers. Blocks swaps in its mock at import time. AWS Emulator answers at the AWS API boundary.
- The Blocks documentation states that no emulator is needed, and the AWS SDK is never loaded during local development. There is no place for AWS Emulator in today's Blocks developer experience.
- At the same time, Blocks has no layer of tests that checks how AWS responds to what its AWS implementations send. Each Block's design document (DESIGN.md) lists many differences between the mock and AWS, and many of them are left to be verified in a sandbox (a temporary environment deployed to real AWS).
- AWS Emulator publishes how closely it matches AWS as a "fidelity score". Taking only the operations that Blocks actually calls, data reads and writes (DynamoDB, S3, SQS and others) matched AWS 80 to 100 percent of the time. Realtime delivery to browsers, email sending, and sign-in flows still score low.
- I started AWS Emulator on GitHub Actions and pointed the Blocks AWS implementations at it without changing any code. KVStore returned the same results as the mock, and FileBucket returned exactly the S3 behavior described in DESIGN.md (lowercased metadata keys and delete-marker handling).
- IAM, data operations on the database (PostgreSQL), throttling, and eventual consistency remain gaps that AWS Emulator does not close.
So the most I can say today is that AWS Emulator does not replace the mocks, but has room to sit between the mocks and the sandbox as a third layer. On top of that, the place where it felt most useful first was not the developer's machine but the Blocks project's own tests.
A quick recap of AWS Blocks
AWS Blocks is an open-source framework that entered public preview in June 2026. It lets you build backends on AWS in TypeScript.
Its building unit is the "Block". There is KVStore for key-value data, FileBucket for files, AsyncJob for background work, Realtime for pushing updates to browsers, several Auth Blocks for sign-in, and more. Each one is distributed as an npm package.
A Block bundles three things: the infrastructure definition for AWS (AWS CDK), the implementation that calls AWS services (AWS SDK), and a local implementation for running on your machine. All three share the same typed API, so your application code does not change between them.
In your backend code, you define a Block like this:
import { Scope, KVStore } from '@aws-blocks/blocks'; const scope = new Scope('my-app'); const sessions = new KVStore<string>(scope, 'sessions'); // Inside an API, call sessions.put('user-1', 'hello') or sessions.get('user-1') There is no DynamoDB table name and no SDK call in this code. When you deploy, KVStore becomes a DynamoDB table, and Blocks also sets up the permissions that let your Lambda functions read and write it.
A Blocks application can run in three ways, and this post depends on keeping them apart.
| Mode | Command | Summary |
|---|---|---|
| Local development | npm run dev | Every Block runs its local implementation. No AWS account needed |
| Sandbox | npm run sandbox | Deploys a temporary, per-developer backend to real AWS and runs on real services |
| Deployment | npm run deploy | Deploys the whole application to AWS with CDK (CloudFormation) |
The CLI reference covers the commands in detail.
In this post, "mock" means the local implementation from the first row, and "sandbox" means the temporary environment on real AWS from the second row.
What AWS Emulator is
AWS Emulator reproduces the AWS APIs on your machine. You don't need an AWS account, and your requests go to the emulator instead of AWS. There is no additional service fee.
You start the emulator and point the AWS CLI or an AWS SDK at its local endpoint. Your application and test code stay the same, and they read and write resources that live inside the emulator. The state is kept in memory and disappears when you stop the emulator.
It ships as RPM and Debian packages for Linux, and as a Dockerfile for macOS and Windows. There is also an embedded mode for Rust tests that runs an isolated emulator per test, and a skill for AI coding agents so you can let your agent handle the setup.
The service definitions are generated from the same API models that the AWS SDKs are built from. For any service whose API model is published, the shape of requests and responses lines up with AWS. When AWS adds a service or an API, it appears in the emulator, and its behavior is filled in release by release. Operations whose behavior is not implemented yet return 501 Not Implemented.
What stands out most in this release is how the emulator was built. According to the AWS senior principal engineer who started the effort, the code was written entirely by autonomous AI agents. The team has not written or reviewed any of it.
The starting prompt had three steps: write tests with the AWS CLI, iterate on them until they pass against real AWS, then build an in-memory implementation that passes the same tests.
Tests that have been confirmed against real AWS become the reference, and the agents keep fixing the implementation against them. These reference tests are called fidelity tests, and their results are published with every release as fidelity scores. According to the official explanation, the emulator matches AWS most closely today for control plane APIs, such as creating and deleting resources. Fidelity for the data plane (the main function of a service, such as reading and writing data), and support for CloudFormation and the AWS CDK, varies by service. The analysis later in this post uses the raw data behind these scores.
The repository is open source, but it does not accept pull requests. CONTRIBUTING.md explains that AI agents keep the emulator up to date with AWS, and asks for issues instead.
AWS also states its limits clearly. The README says not to use the emulator for production workloads or to test security. The security page adds that it does not evaluate IAM policies or resource-based policies the way AWS does, so a request that AWS denies might succeed in the emulator, and the reverse can also happen.
Tools that reproduce AWS locally are not new. The AWS SAM CLI can run Lambda functions and API Gateway locally, and the third-party LocalStack has been around for a long time. In 2025, AWS itself added LocalStack integration to the AWS Toolkit for VS Code.
What is new about AWS Emulator is that it is official, that it generates nearly every service mechanically from the API models, and that it keeps publishing how closely it matches AWS as a score.
Two kinds of "local"
Both tools run locally, but they replace AWS at very different points.
AWS Blocks switches implementations with Node.js conditional exports. You list a file for each condition under exports in package.json, and Node.js picks the file that matches the current context. Here is what the KVStore package.json contains:
"exports": { ".": { "browser": "./dist/index.browser.js", "cdk": { "default": "./dist/index.cdk.js" }, "aws-runtime": "./dist/index.aws.js", "default": "./dist/index.mock.js" } } By default you get the mock. During CDK synthesis you get the CDK construct. Only when the backend is bundled for Lambda does the aws-runtime condition load the implementation that uses the AWS SDK. The local development guide says that each Block ships a local implementation with the same typed API as production, so no emulator or additional tooling is required. It also says the AWS SDK is never loaded during local development.
AWS Emulator works one layer below. As described above, it receives the SDK calls themselves and returns the same shape of responses and errors as AWS.
Here is how the two relate:
Application code (new KVStore(...)) │ ├─ npm run dev (default) ──→ Blocks mock … reproduces the Blocks API │ └─ aws-runtime condition ──→ Blocks AWS implementation │ └─ AWS SDK │ ├─ AWS_ENDPOINT_URL ──→ AWS Emulator … reproduces the AWS API │ └─ AWS The two also reproduce different things.
The Blocks mock reproduces the Blocks APIs, such as KVStore and FileBucket. When you write a value to KVStore, the mock stores it directly in local files or memory without going through DynamoDB. No DynamoDB request or response appears anywhere.
AWS Emulator reproduces the AWS APIs, such as DynamoDB and S3. It answers the requests that arrive from an SDK or the CLI in the same shape that DynamoDB or S3 would.
Because they reproduce different things, AWS Emulator has no place in today's Blocks developer experience. npm run dev never calls the SDK, so there is nothing to point at the emulator in the first place.
Neither repository mentions the other. The only hit for "emulator" in the Blocks repository is a pull request about the Android emulator.
The gap in how Blocks tests itself
Does that mean AWS Emulator has nothing to offer Blocks? Not quite. What caught my attention was how Blocks tests its AWS implementations.
KVStore has parity tests that keep the mock and the AWS implementation behaving the same way. Here is how the AWS implementation is exercised:
/** * Capture what the AWS runtime would send to DynamoDB and control what it reads * back, without touching the network. Real `KVStore`, real `PutCommand`. */ function captureAws(id: string, respond: () => any = () => ({})) { const store = new AwsKVStore<string>({ id: 'root' } as any, id); const sent: any[] = []; (store as any).docClient.middlewareStack.add( (_next: any) => async (args: any) => { sent.push(args.input); return { output: respond() }; }, { step: 'initialize', name: 'kv-parity-intercept', override: true }, ); return { store, items: () => sent }; } The code does exactly what the comment says, in three steps.
First, it creates the real AWS implementation of KVStore (AwsKVStore). Next, it adds a middleware to the DynamoDB client inside it. Middleware in the AWS SDK for JavaScript v3 lets you run code before and after a request is sent. This middleware records the request in sent, never sends it to DynamoDB, and returns whatever respond() returns as the response.
In other words, the DynamoDB response the test receives is a value the test author prepared in respond. Real DynamoDB is never called from start to finish.
So this approach can verify what the AWS implementation sends, and nothing more. How DynamoDB responds stays within what the test author assumed.
The same gap shows up in each Block's DESIGN.md. Many Blocks have a "Mock vs AWS Behavior Differences" table that honestly lists where the mock and AWS behave differently, and "verify in a sandbox" appears again and again in the mitigation column. For FileBucket, the differences include how S3 handles delete markers, lowercased user metadata keys, and the error codes returned for an unknown versionId.
There is also one telling pull request. PR #999, merged in October, checks the CDK bootstrap status before deploying. Its verification notes say the maintainer pointed AWS_ENDPOINT_URL at a hand-made fake STS/SSM endpoint to exercise the real SDK clients and error handling without an AWS account.
The maintainers needed a way to reproduce AWS responses locally and built one on the spot. That is exactly where AWS Emulator could fit.
Running the same operations against the mock and the emulator
To see what this gap looks like in practice, I wrote a small script that runs the same operations against both the Blocks mock and the Blocks AWS implementation pointed at AWS Emulator. As I explain later, the place where AWS Emulator felt most useful first was testing in CI. So instead of my own machine, I started the emulator on a GitHub Actions Linux runner.
Setting up the emulator was just a matter of installing the published RPM and starting it. On startup it writes three files to ~/.aws/emulator/9297/: config with the endpoint and certificate location, emulator_credentials with the credentials, and the self-signed certificate ca.pem. To run the AWS implementation, I set these environment variables and loaded the Block with the aws-runtime condition:
D=~/.aws/emulator/9297 export AWS_CONFIG_FILE=$D/config export AWS_SHARED_CREDENTIALS_FILE=$D/emulator_credentials export NODE_EXTRA_CA_CERTS=$D/ca.pem # make Node.js trust the self-signed certificate export AWS_ENDPOINT_URL=https://127.0.0.1:9297 node --conditions=aws-runtime --import tsx probe.ts --aws I did not touch the Blocks AWS implementation code. Neither KVStore nor FileBucket hard-codes an endpoint when creating its SDK client, so the environment variables alone were enough to redirect them.
The table and bucket did have to exist beforehand, though. They are normally created by CDK at deploy time, so I created them directly with the SDK. A DynamoDB table starts in the CREATING state, and writing to it right away returns ResourceNotFoundException. That matches real DynamoDB, and I had to wait about three seconds before the table was usable. The mock never has this wait.
I used AWS Emulator 1.0.322 and the latest Blocks packages on npm (blocks 0.9.0, bb-kv-store 0.4.0, bb-file-bucket 0.4.0). For KVStore and FileBucket, I picked operations that DESIGN.md lists as differences.
| Operation | Blocks mock | AWS implementation + AWS Emulator |
|---|---|---|
| Write to KVStore and read it back | The written value | The written value |
Write to an existing key with ifNotExists | ConditionalCheckFailedException | ConditionalCheckFailedException |
| Write with an expired TTL, then read | null | null |
| Write a 450 KB value | ItemTooLargeException | ItemTooLargeException |
Write to FileBucket with metadata Owner, then read | Key stays Owner | Key becomes owner |
| Read with an unknown versionId | null | null |
| Restore an unknown versionId | NoSuchVersion | NoSuchVersion |
| Overwrite across a delete marker, permanently delete the current version, then read | replacement | null |
The four KVStore rows returned the same results from the mock and from the emulator. The behavior that DESIGN.md describes as aligned between the mock and AWS came back the same way through the AWS implementation.
The differences appeared in two FileBucket rows.
Metadata keys came back unchanged from the mock and lowercased from the emulator. DESIGN.md explains that S3 lowercases user metadata keys, so code that reads metadata.Owner works locally and gets undefined on AWS. The emulator reproduced that S3 behavior. A difference that DESIGN.md could only describe in words became visible as a test result.
The last row is easier to follow with S3 versioning in mind. A bucket with versioning enabled keeps past versions when you overwrite or delete an object. Deleting by key alone does not remove data. Instead, a "delete marker" is stacked on top as the latest version, and reads then see the object as deleted. Only deleting a specific version (by versionId) removes that version permanently.
The steps follow the DESIGN.md table exactly:
put('old') delete() ← versioning is on, so a delete marker is added put('replacement') delete(current versionId) ← permanently deletes replacement get() DESIGN.md says the mock returns old here, while S3 makes the earlier delete marker current and treats the key as deleted. The emulator returned null, exactly as described for S3.
The latest mock on npm, however, returned replacement, the version that had just been permanently deleted, not old. It turns out this mismatch was already fixed by PR #693, merged the day after 0.4.0 was published. The fix replaces the local current copy with the next version when the current version is permanently deleted. Reading the code on main, the mock should now return old as DESIGN.md says. The fix has not been released yet, so the npm version still shows the old behavior.
That leaves three different answers to the same steps: null from the emulator reproducing S3, old from the mock on main, and replacement from the published mock. The difference between old and null is documented in DESIGN.md as a known gap.
This is not something you are likely to hit in day-to-day development. Still, it shows the nature of the gap well. Even with a table of mock-versus-AWS differences and tests of what the AWS implementation sends, this kind of drift cannot be caught by any single test unless there is a layer that checks how AWS actually responds. You only find it by laying the mock, DESIGN.md, and real AWS behavior side by side. Doing that check with AWS Emulator confirmed that the S3 behavior written in DESIGN.md comes back exactly as described.
The ItemTooLargeException row for KVStore deserves a mention too. The KVStore AWS implementation checks whether the message of a ValidationException from DynamoDB contains "size has exceeded" with a regular expression, and turns it into ItemTooLargeException. The conversion depends on the wording of the message, not the error type. It worked against the emulator because the emulator's DynamoDB implementation defines the message "Item size has exceeded the maximum allowed size" as a constant that matches AWS.
Being generated from API models only means the shape of requests and responses matches AWS. The source shows that AWS Emulator also tries to match the wording of error messages. For a library like Blocks that reinterprets errors based on their wording, this makes a real difference.
Gaps AWS Emulator can and cannot close
So how much of what Blocks calls does AWS Emulator reproduce today?
AWS Emulator publishes fidelity scores with every release. The v1.0.322 release attaches the raw evaluation data as scores.json.gz. It records, for each short scenario (a sequence of calls such as creating, reading, and deleting a resource), whether the emulator's responses matched the ones recorded on AWS.
At the service level, DynamoDB, S3, and SQS pass roughly 60 to 70 percent. That number is not very useful for Blocks, though, because Blocks calls only a small subset of each service's operations.
So I listed the SDK clients that each Block's AWS implementation imports, narrowed the data down to the operations they actually call, and recomputed the match rate per step within each scenario.

Built from scores.json.gz in aws/aws-emulator v1.0.322
A few caveats apply. Only the tests classified as "wire" in scores.json carry per-step detail, and they make up about a quarter of the total. Operations with single-digit step counts are too few to read even a trend. The official documentation also explains that adding tests can surface differences that were already there as new failures, so a score should be read as a snapshot. What you see here is a trend at one point in time.
Even so, the split between operations that are already reproduced and those that are not is clear.
The operations called by the data-oriented Blocks (KVStore, DistributedTable, FileBucket, enqueuing in AsyncJob, Secret, AppSetting) have high match rates. Among the differences that DESIGN.md says to check in a sandbox, those about the shape of DynamoDB and S3 responses or their error codes are candidates for checking with AWS Emulator instead.
On the other hand, Realtime delivery to browsers, email sending in EmailClient, and the sign-in flow in AuthCognito do not look ready to be verified with the emulator yet.
And regardless of the scores, some gaps remain that AWS Emulator does not close.
The first is IAM. The DESIGN.md files of several Blocks, including KVStore, FileBucket, and AsyncJob, list "No IAM enforcement" as a difference, and the AWS Emulator README also says not to use it for security testing. According to the official security page, some services evaluate the policies of IAM users and roles that you create inside the emulator, but not the same way AWS does. Requests signed with the emulator's own keys are never denied. Blocks wires permissions automatically through CDK grants, and for now the only place to check that they are correct is a sandbox.
The second is the database. The Database and DistributedDatabase Blocks connect to PostgreSQL-family databases on AWS, such as Aurora Serverless v2 and Aurora DSQL. AWS Emulator does have an Aurora DSQL service, but it implements only management operations such as creating and deleting clusters. The path that runs SQL is not an AWS API, so it belongs to PGlite in the Blocks mock or to a sandbox, not to the emulator.
The third is behavior that depends on timing and scale, such as throttling and eventual consistency. Blocks itself treats these as inherently non-deterministic in DESIGN.md and offers no mitigation, and it is hard to expect the emulator to cover them either.
One more thing worth noting is that CloudFormation scores only around 20 percent at the service level. The official documentation also says that support for CloudFormation and the AWS CDK varies by service. Since a Blocks application is a CDK application, deploying a Blocks template to the emulator as-is to run the whole AWS implementation does not look practical yet.
Blocks testing in three layers
Putting this together, Blocks testing can be thought of in three layers.
Blocks mock AWS Emulator Sandbox (real AWS) types, logic, usage ··> API responses and errors ··> IAM, performance, eventual consistency │ ▲ └──────── bridged today by the DESIGN.md difference tables ┘ | Layer | What it can verify | What it cannot verify |
|---|---|---|
| Blocks mock | Types, business logic, how Blocks are used, the feel during development | How AWS responds |
| AWS Emulator | The requests the AWS implementation sends, and the shape of the AWS API responses and errors | IAM, PostgreSQL data operations, timing and scale |
| Sandbox (real AWS) | Real behavior, including permissions, performance, and eventual consistency | Speed and convenience |
Today, Blocks has the first and third layers. The DESIGN.md difference tables bridge the space between them in prose. With AWS Emulator in between, some rows of those tables might move from "be careful" in prose to "verified" by tests. The metadata and delete-marker rows in this post are examples of exactly that.
What I expect for AWS Emulator and Blocks
From here on, this is my own expectation based on public information. It is not something AWS or the Blocks maintainers have said.
The first thing I expect is AWS Emulator showing up in the Blocks project's own tests. The parity tests' captureAws returns hand-written DynamoDB responses. Replace that with responses from the emulator, and the tests could check not only what the AWS implementation sends but also how AWS responds, inside CI and without an AWS account. There would be no need to hand-build fake endpoints for each verification, as in PR #999.
Use on developers' machines would likely come next. For example, a mode separate from npm run dev that runs the AWS implementations against the emulator. As the run above showed, loading the Blocks with the aws-runtime condition and pointing the SDK at the emulator through environment variables was enough to run the AWS implementations without an account. The foundation already exists.
There are two challenges before that happens.
The first is who creates the resources. The AWS implementations assume that the tables and buckets created by CDK already exist. In my run, I created the table and bucket with the SDK by hand and wrote the code to wait for the table to become usable. Judging by the CloudFormation scores, deploying the template to the emulator is not practical yet, so Blocks would need a separate way to prepare resources for the emulator.
The second is keeping the simplicity that Blocks local development promises. Blocks local development needs no AWS account, no internet connection, and no running container daemon. AWS Emulator, on the other hand, installs as a package on Linux but needs Docker on macOS and Windows. Requiring the emulator would give up the "nothing to set up" simplicity.
That is why I don't think the mocks will go away. There are gaps the emulator cannot close, such as PostgreSQL data operations and IAM. And the experience of running everything with just npm run dev is at the heart of what Blocks offers. With both in mind, it seems natural to position AWS Emulator not as a replacement for the mocks, but as an option that sits between the mocks and the sandbox.
Why "AWS Emulator makes the mocks unnecessary" doesn't hold yet
There is an opposing view. If an official emulator returns the same responses as AWS, wouldn't it be cleaner for Blocks to rely on it than to keep writing and maintaining a mock for every service?
The cost of maintaining the mocks is certainly not small. The DESIGN.md difference tables are long for every Block, and as the FileBucket drift in this post shows, the tables and the implementation can fall out of sync. AWS Emulator, by contrast, is maintained by AI agents that keep running fidelity tests and fixing the implementation, and the issues/ directory in its repository shows fixes accumulating over time.
Still, there are two reasons to be careful about replacing the mocks right away.
The first is that the mocks and the emulator reproduce different things. The Blocks mocks reproduce the types and error contracts of Blocks. The emulator reproduces the AWS APIs, so even with the emulator you still need the Blocks AWS implementations, which means more moving parts on your machine.
The second is the set of challenges above: Docker, preparing resources, and the database and IAM gaps. Putting those on users would move Blocks away from its experience of not having to think about AWS. In my previous post, I described Blocks as letting you be aware of the infrastructure without requiring you to be. Testing is the same: AWS Emulator fits the Blocks philosophy best as a layer that people who want that awareness can step down into.
Closing thoughts
When I learned about AWS Emulator, the first question that came to mind was whether the Blocks mocks were about to become unnecessary.
Reading the source of both projects, though, the two replace AWS at different layers to begin with. The Blocks mocks reproduce the API that Blocks exposes to its users. AWS Emulator reproduces the AWS APIs underneath it.
And between those two layers sits a gap that Blocks testing cannot yet cover: the DESIGN.md difference tables, the parity tests built on hand-written responses, and the fake endpoint a maintainer built by hand. That is where AWS Emulator fits most naturally.
AWS Blocks is still in public preview, and AWS Emulator has only just been released. Both are open source, so where the two meet should become visible by following their repositories. I'm looking forward to seeing whether the first point of contact shows up in the Blocks project's own tests or on developers' machines.
![Industrial Communication — Ch.10: Factory Automation [EN]](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft1hw2kvh64lkchmsurzd.png)

