Illustration of the Dynoxide logo with DynamoDB table icons on a dark background

Introducing Dynoxide: a fast, embeddable DynamoDB engine

I've been working with DynamoDB for the best part of a decade. It's my default database for most things I build at Si Novi, and I genuinely like it. The data modelling is satisfying once it clicks, the operational overhead is basically zero, and it scales without you having to think about it.

Last year, Si Novi started building Nubo, a native DynamoDB client for macOS and iPadOS, with Windows and Linux on the way. One of the features we wanted from the start was a built-in sandbox. A local DynamoDB instance running on-device that you could experiment with, no AWS credentials needed. Create tables, insert data, test access patterns. All offline. All on your machine. Maybe even on an iPad.

The problem was: how do you ship that?

DynamoDB Local's licence explicitly prohibits redistribution. You can't bundle it inside another application or sublicence it. Even setting the licence aside, the developer experience would have been awful. Asking users to separately download and install a Java-based emulator, with Docker or a JVM as a prerequisite, just to use one feature in your app? That's not a sandbox. That's homework.

And on iPadOS there's no path at all. No JVM. No Docker. Nothing.

So I started building something new. A DynamoDB-compatible engine in Rust, backed by SQLite, that compiles to a single native binary. Something I could embed directly into Nubo as a library.

That's how Dynoxide started.

From library to tool

The first version did exactly what I needed: a local DynamoDB that Nubo could bundle as its sandbox. Job done, in theory. But the thing that surprised me was just how small and fast it turned out to be.

A ~3 MB download (~6 MB on disk). Under 5 MB of RAM at idle. Cold startup in about 15 milliseconds, compared to over two seconds for DynamoDB Local. Numbers like that change what's practical. Instead of running one shared DynamoDB instance in your CI pipeline, you could spin up a fresh one per test. Isolated state. No cleanup step. No flaky tests from leftover data. Tear it down when you're done and the overhead is essentially nothing.

That realisation shifted what Dynoxide was becoming. It wasn't just infrastructure for Nubo any more. It was a tool in its own right.

The same properties that made it good for CI made it a natural fit for agentic development. A coding agent that needs to create tables, write data, or test queries can do all of that through Dynoxide's built-in MCP server. 34 tools, no setup required. Run dynoxide mcp and your agent has a full DynamoDB environment to work with.

And then I looked at how many Node.js projects still depend on dynalite for local DynamoDB. I owe a lot to dynalite. Using it through arc.codes and Architect is what turned DynamoDB from a database I'd reach for occasionally into the one I'd reach for first. Having a fast local emulator that just worked changed how I thought about building with DynamoDB. It made the feedback loop tight enough that I actually wanted to experiment. But dynalite hasn't seen updates in a while and newer DynamoDB features like transactions and streams aren't covered. Dynoxide supports both, along with the rest of the API surface. With an npm package shipping platform-specific binaries (the same approach esbuild and Biome use), it works as a drop-in replacement. Same workflow, one line change in your package.json.

Under the hood

Dynoxide implements the DynamoDB API as a translation layer in Rust, storing data in SQLite and compiling to a native binary with no runtime dependencies. DynamoDB Local takes the same general approach (SQLite as the storage engine is well documented) but ships as a Java application with a JVM dependency and a restrictive licence.

Because SQLite is an embedded database, Dynoxide doesn't have to run as a standalone server. It can be linked directly into another application, which is exactly how Nubo uses it. Encrypt the database file with SQLCipher and you've got a portable, encrypted, DynamoDB-compatible data store. Nubo uses this for its local cache: data you've previously accessed from AWS is kept in an encrypted database on-device, so it loads instantly and works offline.

To make sure Dynoxide actually behaves like the real thing, I built a conformance test suite. 526 tests, all validated against real DynamoDB on AWS. Every emulator gets the same suite. Dynoxide passes all 526. DynamoDB Local manages 92%. LocalStack gets 93%. Dynalite hits 81%.

The suite is public. Anyone can run it and verify.

Get started

Homebrew:

brew install nubo-db/tap/dynoxide

npm (drop-in dynalite replacement):

npm install --save-dev dynoxide

Cargo:

cargo install dynoxide-rs

Then just run it:

dynoxide

Full documentation is at dynoxide.dev, and the source is on GitHub.


Dynoxide is the foundation. But the thing I'm building on top of it is what I really want to talk about next. Nubo is a native DynamoDB client for macOS and iPadOS, and I think people who work with DynamoDB day to day will love it. If that sounds interesting, there's a mailing list at nubo.sinovi.uk.

Dynoxide stands on its own though. If you're running DynamoDB Local in CI and wondering why your pipeline is slow, or you're still using dynalite and need coverage for newer API features like transactions and streams, give it a try. I'd love to know what you think.

Si Novi will be at AWS Summit London on April 22nd. If you're there and want to talk DynamoDB, come and find me.