Canic ❤️ Motoko

We are exploring whether Motoko canisters could participate as fully managed Components inside a Canic Fleet.

The short answer appears to be: yes, this is technically feasible.

However, this would be an interoperability feature—not a rewrite programme.

What We Are Considering

A Motoko application canister would be able to:

  • be built and qualified through Canic;
  • be installed from the Fleet Subnet Root’s Wasm Store;
  • participate in Canic’s managed Directory and activation lifecycle;
  • report its protected identity and runtime status;
  • request admitted child canisters through its Fleet Subnet Root; and
  • call separately deployed Rust services over Candid.

The intended topology looks roughly like this:

Canic host
    |
    | Cargo or qualified Mops build
    v
Fleet Subnet Root + Wasm Store
    |
    +-- Rust Component
    |
    +-- Motoko Component
            |
            | typed Candid calls
            v
        Rust IcyDB service

The Fleet Subnet Root remains the Canic deployment and Registry authority.

What This Does Not Mean

To be completely explicit:

We do not intend to rewrite Canic, IcyDB, or any of our existing Rust products in Motoko.

The following remain Rust:

  • Canic’s host, CLI, runtime, core, macros, backup system, and control plane;
  • Fleet Coordinator, Fleet Subnet Root, and Wasm Store;
  • IcyDB’s schema, planner, indexes, execution engine, storage, recovery, and migrations; and
  • all existing Rust application and service products.

The only Motoko code Canic might maintain would be a small interoperability layer:

  • bounded Candid wire types;
  • managed lifecycle helpers;
  • a root-capability client;
  • explicit actor-scaffold support; and
  • conformance fixtures and examples.

That SDK would be a protocol adapter, not a Motoko implementation of Canic.

Why It Appears Feasible

Much of Canic is already language-neutral.

The Wasm Store, release sets, module hashes, installation machinery, Component Registry, Directories, snapshots, backup, and restore operate on Wasm bytes, hashes, principals, and Candid—not Rust source.

The Rust-specific boundaries are primarily:

  • Cargo-based role declarations and qualification;
  • Cargo build execution;
  • Rust build-time identity injection;
  • the current Rust-owned initialization payload;
  • macro-generated lifecycle endpoints; and
  • Rust client bindings for root capabilities.

Those boundaries could potentially be replaced with:

  1. one compact, language-neutral managed-guest ABI;
  2. a qualified and pinned Mops builder;
  3. an explicit Motoko actor scaffold; and
  4. shared Rust/Motoko conformance tests.

One Important Wire Rule

Motoko’s documentation correctly warns that different valid Candid byte encodings can represent the same value.

A guest must therefore not decode a value, call to_candid, and hash the result as deployment evidence.

Instead:

  1. the root encodes and freezes an authority payload once;
  2. the root hashes those exact bytes;
  3. the guest validates the supplied bytes and digest;
  4. the guest stores the original bytes unchanged; and
  5. the guest may decode them for use, but must never re-encode them to establish identity.

This gives Rust and Motoko one exact evidence boundary without requiring both languages to produce byte-identical Candid encodings independently.

Mops Build Requirements

We do not want an arbitrary external build command or shell hook.

A qualified Mops build would need to bind and preserve:

  • an exact Mops CLI version;
  • an exact moc version;
  • mops.toml and mops.lock;
  • contained source and dependency paths;
  • the selected canister;
  • the generated Canic build identity;
  • emitted Wasm, DID, and MOST files;
  • source-tree non-mutation; and
  • reproducible artifact hashes.

Builds should run in isolated staging and output directories. Canic should remain the sole owner of any post-build Wasm transformations.

The IcyDB Path

We do not propose porting IcyDB to Motoko.

Instead, a Motoko application could request a schema-specific Rust IcyDB child from its Fleet Subnet Root and call an application-facing Candid API.

The Motoko parent would not control the database canister. Canic would retain controller and deployment authority, while the IcyDB service would authorize its exact registered parent for application operations.

The first service style would probably be typed and schema-specific:

Motoko application
    |
    | ensure admitted database child exists
    v
Fleet Subnet Root
    |
    | installs and activates
    v
Rust IcyDB service
    |
    | typed, bounded, parent-authorized Candid API
    v
Application data

Cross-canister writes are not same-process transactions, so mutations would require durable operation IDs and exact retry receipts.

First Step: A Feasibility Proof

Before changing any production API, we want to run a bounded investigation that proves:

  • one candidate managed-guest Candid contract;
  • identical golden decoding and hashing in Rust and Motoko;
  • a real persistent Motoko actor with explicit managed endpoints;
  • an isolated, pinned, source-non-mutating Mops build;
  • lifecycle preparation, synchronization, activation, and status;
  • exact retry and conflicting-operation rejection;
  • recovery after response loss and restart;
  • same-contract upgrade behaviour; and
  • a clear distinction between Canic activation and application readiness.

No public SDK, configuration change, or managed-Motoko support claim would be made until that proof succeeds.

Questions for Motoko and Mops Developers

We would especially appreciate feedback on the following:

  1. Would you use managed Motoko Components inside a Rust-operated Canic Fleet?
  2. Would you prefer a checked-in generated actor scaffold or a small, explicit set of lifecycle forwarding methods?
  3. What is the cleanest current Mops mechanism for injecting a generated package during a build without modifying mops.toml or mops.lock?
  4. Which Mops and Motoko toolchain assumptions tend to cause reproducibility problems in CI?
  5. Would a generated typed Motoko client for a schema-specific Rust IcyDB service be useful?
  6. Would you need a reduced, parent-only SQL API, or would typed CRUD and query methods be preferable?
  7. What upgrade and stable-state behaviour would you expect from a managed Motoko guest?
  8. Are there important Motoko lifecycle or persistence constraints that this architecture overlooks?

This is currently an architectural exploration, not a shipping announcement.

The goal of the first phase is to discover any hard blockers before committing Canic’s production ABI or publishing an SDK.

Aye mate. I’m not much of a backend engineer. More of a front end toymaker.

But what I do know is that serialization and deserialization in candid is a bloody nightmare it is.

And it appears you are making it easier for people to do that at scale, and now for people who don’t even rust.

This seems like a good thing mate. Keep it up.

Thanks, the intention is to allow everybody to scale on this platform, not just us rusties. I don’t think the explanation of what canic actually does is that clear, I’ll improve that.

Bit weird that the foundation puts millions of dollars into Caffeine and other apps… but when something comes along that has the potential to scale a Motoko app to 10 million canisters it’s just silence. I think I may be shadowbanned!

If you can activate the ICP ecosystem, your technology will be unparalleled

You could add in the mops command line args something like this:
mops build -- --package test "/my/path/to/package.mo"

Not that I can think of.

However, please point claude to the recent motoko developments and skills: https://skills.internetcomputer.org/

there’s stuff there about mops, icp cli, motoko etc.

Check out the upcoming mops v3 that is currently in beta (code here https://github.com/caffeinelabs/mops/tree/v3 ; changelog here https://github.com/caffeinelabs/mops/blob/v3/cli/CHANGELOG.md; docs here https://docs.mops.one/next ). This version should already be an improvement for you, it’s published on npm only for now (e.g. https://www.npmjs.com/package/ic-mops/v/3.0.0-beta.2).
I am analyzing your usecase and identifying gaps in mops that we can solve to help with reproducibility. Feel free to open an issue if you see sth missing

Ok thanks, going to feed a lot of this into the design.

Soon will be asking for volunteers, who wants to make a game that spans 10 subnets just for kicks?

In general, I think motoko peeps need to better understand what you are trying to provide and what the benefits are. I know I could go back and read all the canic/icyDB docs, but I’m lazy, and you send me knife emojis, which tends to dissuade me from going the extra mile :joy:.

I’m glad the knife emoji landed.

I’m going to get Donna to help out with the readme for canic. I did update it today but could do with a little more explanation. It’s just like Kubernetes for the IC and imo, it’s going to be very hard for any application to scale without it (including Caffeine made apps and multi/dex).

Here is some copypasta

Features

Each feature has a short guide of its own. The guides explain the capability and its authority boundary, then point to the detailed contracts and runbooks.

Canister Runtime

Lifecycle and build macros, stable-memory helpers, timers, typed calls, metrics, and configuration-derived runtime context for Rust canisters.

Explore the canister runtime

Authentication

Endpoint guards, delegated subject tokens, root-managed chain-key proof renewal, issuer proofs, role attestation, and explicit caller/subject binding.

Explore authentication

Fleet Orchestration

Coordinator-backed Fleet installation, one root and Wasm Store per occupied Subnet, qualified artifacts, registries, directories, and root-owned platform effects.

Explore Fleet orchestration

Scaling And Placement

Reusable Component Specs and Groups, bounded placement, service roles, dynamic child trees, sharding pools, scaling pools, and reduction-only limits.

Explore scaling and placement

Builds, Provenance, And Evidence

Role-aware Wasm builds, build provenance, passive deployment evidence, policy gates, adoption reports, and network-scoped Fleet catalogs.

Explore builds and evidence

Backup And Restore

Topology-aware canister snapshots, manifests, checksums, resumable download journals, verified restore plans, and guarded execution from the host CLI.

Explore backup and restore

Blob Storage

Optional runtime APIs and operator tooling for product blob storage, with the non-billing integration kept separate from Cashier-backed billing support.

Explore blob storage

Operations And Diagnostics

App and Fleet setup, network trust, local replicas, installation, status, inspection, medic checks, recovery guidance, and automation-friendly output.

Explore operations and diagnostics

The complete feature index is in docs/features.

Demo Fleets

Skynet combines Fleet services, multi-Subnet placement, scaling, sharding, metrics and protected runtime discovery in a Terminator-themed live network console. Its checked-in App starts with eight Authority/Replica nodes and can prepare one member on each of up to 32 distinct workload Subnets.

Explore the Skynet Fleet demo

https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExZmR3Z3pkdG15M3A0NHRld2ZhNnkyYmdjZnoxMTd3ZHM1cXl2Z2E5eCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/rCkSNca7Vv81ENAq2b/200.webp

You just broke all the things.

https://media0.giphy.com/media/v1.Y2lkPWVjZjA1ZTQ3NDI2cnFheTJzanhoaWtpNmp2aWR5NHAxdzFtdTIxeGoxeHB6MWdhayZlcD12MV9naWZzX3NlYXJjaCZjdD1n/y0xuS673FdIbvjXAwK/giphy.webp

SHUT.

EVERYTHING.

DOWN.

(and more characters, and apparently even some more)

Damn it, the LLM was not supposed to talk about Skynet.

I mean, it’s not going to make any difference soon anyway. Jus’ like holdin’ yer thumb up and it ain’t as tall as the mushroom cloud.