Anytwo - updates to infrastructure

During the latest Town Hall, we explained how we re-built the infrastructure underneath the app to make it better. Here is post that gives the technical outline of how Anytwo will have:

  • Better data integrity
  • Better sync
  • Better performance

Some context

Anytype is a local-first product, which means you get all the benefits of cloud products but without the sacrifices to your privacy, security, and sovereignty. You should always have access to your data, be able to use it offline by default, and all syncing should be end-to-end encrypted. Local-first technology is new and still being developed today. Back when Anytype started in 2019, local-first was just an idea. This means that we had to build our own tech stack from scratch and prove that it works while also building a product that users would love to use. Like all things, we have clear answers today that were impossible questions back in the day.

Anytype is able to serve many users today well, but its flaw is that every time we add new features, it comes at increasingly higher costs: new bugs are created in other areas, issues are difficult to diagnose, and it has a huge impact on development resources. Much of this is due to the unique quirks surrounding the way encryption and offline-first technology works (local-first CRDTs and DAGs).

In short, maintaining a high quality product required disproportionate effort, and new releases kept introducing regressions. These higher resource requirements and slower development pace put us at a disadvantage that stacks over time. This is why we underwent the experiment to see if we could rebuild our infrastructure based on all our learnings over the past 6+ years. And thankfully, the bet we made paid off. This is why we could finally share Anytwo with you all.

As requested, below are some technical outlines of two areas where we’ve made big changes. It’s not all the changes, because that’d be too overwhelming.

Replacing Middleware

Think of the Anytype tech stack as client (the app) <> middleware (the logic) <> any-sync (the protocol). Middleware acts as a bridge between what happens in the app to what gets put through encrypted sync.

1. How the middleware became what it is

Four things shaped it, and all four still weigh on it today.

It grew by accretion. It started in 2019 for one use case — a block editor. Then relations, our own sync, collaboration, templates, chats, and years of features on top. Some were good, some weren’t.

Its foundations were replaced under it. Sync went go-threads → our own DAGs on go-threads → any-sync. The local database went badger → SQLite → any-store. Each move left traces in the layer above.

Its history can’t be rewritten. Local-first and CRDT-based means the DAG keeps every change ever made, like commits in git — including the bugs, the abandoned approaches, the old versioning schemes. It’s encrypted and signed by users, so nobody can rewrite it. The middleware has to keep understanding all of it, forever.

It carries two CRDTs and too many jobs. One CRDT for the editor, which isn’t universal — nearly every block type has its own operations. And a second one from a new approach we introduced with chats: a handful of generic operations, working directly with any-store, proven in production on many chats with thousands of messages. Around them sits everything else: encryption, driving low-level any-sync, the full-text index, import and export, clipboard handling, even the client’s cursor position.

None of this was wasted. It’s how we learned what works and what doesn’t — and the second approach is what we build on next.

2. What’s changing

The infrastructure under the application is now split into layers with clear responsibilities, built on the parts that proved themselves over real use in Anytype.

  • any-sync stays what it is: the low-level framework — networking, encryption, the DAGs, ACL, and the rest of the plumbing. Powerful, but hard to learn and hard to use.
  • anytwo-db glues the any-sync components together and presents them as something understandable. It takes the approach that worked — the one we introduced with chats — and polishes it into a single universal CRDT: faster, more flexible, not tied to any product feature. On top of it come the rules for how data is represented and lands in the database: multitypes, datasets, properties, schemas, versioning. The bet is that almost any business logic can be expressed on this structure while the data representation stays standard and consistent. To express how much clearer it is, the AnytwoDB is approachable enough that even an AI agent can write an app against it—which is impossible on middleware.
  • any-store v2 underneath is faster and adds aggregations, full-text and vector search.
  • any is the high-level layer: it uses the AnytwoDB, defines the basic types, adds search, and exposes a plain JSON REST API — no gRPC, no protobufs. The API is as simple as we could make it while still allowing complicated logic to be built around it.

The rule that holds the stack together: product logic stays above the API, and every layer below it is product-agnostic. That boundary is much easier to draw now that we know, from the middleware, exactly where it belongs. To be clear, we could not have learned these lessons without experience with Anytype. There were no industry best practices to leverage for local-first software.

3. So is it just a rename?

Not a rename. The middleware is one component that does everything — sync, encryption, storage, indexing, the object model, and the product. any + the DB is a stack where each layer has one job, and the data model is a standard instead of an accumulation. The middleware also can’t escape its own history; the DB starts from a single, consistent model. To be clear, middleware works and is able to power many companies today using Anytype. But its quirks make it increasingly difficult to develop on.

Business logic now moves to the client — and that makes apps lighter, not heavier. The client isn’t reimplementing sync, CRDTs, encryption or storage; all of that is below the API. What it gets is a backend with almost direct read access to a powerful database and very strictly described rules for writing. Now, the new system can composes queries and writes records instead of asking a monolith for a product-specific endpoint and waiting for it to be implemented. In short, the app no longer needs to go through the complex middleware logic in order to read/write in the database.

New files node

1. What was wrong with v1

Infrastructure. v1 isn’t expensive in absolute terms, but it costs far more than it needs to. It keeps the file index in a large Redis cache server — cold entries are offloaded to S3 and pulled back on access, so Redis holds the currently active spaces and files, and its size grows with how many of them are online. That offloading writes a lot of tiny index keys to S3 on top of the file data itself. It proxies every byte through the node and stores one S3 object per block — so an S3 bucket full of tiny objects and a huge number of API calls per file. Scaling means scaling the central cache along with the network’s active load.

Design. Files are a separate service, and gluing them to spaces is left to the client. In Anytype every file needs its own any-sync object to carry the encryption key, the metadata and the backup-node status. Those objects are offline-first and CRDT-based; the filenode is neither. The two models don’t line up, and the gap between them is where the edge cases live — sync status that doesn’t match reality, deletions that don’t propagate, refcounts that drift.

2. What v2 changes

Infrastructure. No Redis cache server. The node stores only a small local index per space, derived from the space’s own data and rebuilt on demand, so nodes are small and stateless in practice. Bytes never pass through the node — clients talk to the object storage directly. One object per file instead of one per block: far fewer objects, far fewer S3 calls. Since bytes are served straight from the storage, a CDN can be put in front of them — impossible while every byte went through the node. The same holds on the client: one file on disk per file, instead of millions of separate chunks. Files under 4 KB ride inside the space data and never reach the node at all. The result is decentralized by design: no central index, each node responsible only for its own spaces.

Design. Payloads bind to objects, not just to a space: any existing object in the space can carry any number of payloads, so a file no longer needs an object of its own. The v2 node reads the same CRDT data from the same space as the clients do, so backup status is part of the data rather than a separate story to reconcile, and garbage collection follows the space’s own deletions. Concretely: the node signs a receipt when the bytes are stored and the client records it in the space, so “backed up” is a verifiable fact carried by the data — while the node itself never writes into the space.

The tradeoff. v1 deduplicates blocks across spaces, v2 deduplicates whole files inside one space, so the same file in two spaces is stored twice. In practice the loss is small: everything is encrypted, so v1’s dedup only ever worked within a single account anyway.

3. What it means for users

  • Faster uploads and downloads: straight to storage, no proxy hop, no per-block round trips.
  • Reliable “backed up” status, because the node and the client read the same source of truth.
  • Deletions actually free space, and files are cleaned up when the space says so.
  • Much cheaper to run and to self-host — smaller servers, no Redis, much lower storage-provider cost.

As mentioned during the Town Hall, many of these changes are not backwards compatible with Anytype because it’s rebuilt from the ground up. But it’s this approach that should provide much better data integrity, stability, and performance for the app. With the new editor, better markdown support, new API, etc. we hope that Anytwo becomes a place that you can trust your data is safe in.

I hope this informational post was helpful to those who are technically inclined.

Thanks for the writeup, this is very helpful.
I think I remembered (maybe misremembered) from the Town Hall that there would be a 3rd party security audit report to be shared with the community.
Did I remember that correctly, and did it miss it being shared?

Ah yes, we’ll get that shared. We’ve just been very busy as you can imagine. I’ll get the devs to check it for final review and post it later.

No problem,
I figured as much. I also figured that folks who want to get into the weeds about infrastructure changes would also want security updates. Having your answer hopefully preemptively answers some of their questions.

I’m really excited to try Anytwo — it seems like a major improvement over Anytype.

However, I’m a little concerned about how the migration process will work, not only in terms of the data itself, but also the formatting. For example, I have some large documents organized using toggles and toggle headings. Is this kind of formatting expected to be preserved when migrating from Anytype to Anytwo?

As we have expressed during the Town Hall, we will build a migration bridge to make it as smooth as we can. You have to understand that it’s not in our interest for all of our users to suffer massive losses when moving from Anytype to Anytwo, so we are motivated in ensuring this is resolved. Text, toggles, and toggle headings are the least of our worries. :slight_smile:

I’ve been using Claude to transfer test data from my Anytype space over to my Anytwo testing space, and toggles are super easy. The best part about Anytwo toggles is they are basically collapsible containers without any default formatting associated with them. This means that you’ll have much more flexibility in formatting your text. Here’s a quick comparison of the two from a theology course assignment I had in grad school. I used Claude to import the Anytype document on the right into Anytwo on the left. Mind you this was like 7 minutes of getting Claude to match the links and formats. Whatever the official bridge is will be MUCH better.

Thank you very much for your answer!

Very interesting, thanks for sharing.

Can’t wait to have access to AnyTwo and testing how things are taking shape.

Filled the form several times, no news.

Please don’t do that. It only makes data processing for us more difficult and doesn’t increase your chances.

Yes, sorry.
As I haven’t received any confirmation, I didn’t know if it was recorded or not.
Don’t want to add you more work.