Cloud Engines run backends written in Motoko, a language designed for the Internet Computer. If you've used JavaScript, Python, or Swift, the syntax will feel familiar — but a few ideas are new, especially how Motoko stores data. This guide walks you through writing, understanding, and deploying a small but complete backend.
Prerequisites: the OpenCloud CLI installed and signed in, and a Cloud Engine created (or create one as part of this guide).
The core idea: actors and orthogonal persistence
A Motoko backend is an actor — a self-contained program that holds its own state and exposes functions other code can call. The functions are your API.
The part that surprises most newcomers: there is no separate database. Your data lives directly in the actor's variables, and the platform keeps it there automatically across calls and upgrades. This is called orthogonal persistence. You don't open connections, write queries, or manage a DB — you just declare a variable.
To make sure a variable survives a code upgrade, mark it stable.
Step 1 — Write the actor
Here's a complete backend: a simple counter with a greeting. Save it as main.mo.
actor Counter { // `stable` means this value persists across upgrades. // No database required — orthogonal persistence handles it. stable var count : Nat = 0; // An `update` function changes state. It's persisted automatically. public func increment() : async Nat { count += 1; return count; }; // A `query` function only reads state — it's faster and doesn't // modify anything. public query func get() : async Nat { return count; }; // Functions take typed arguments and return typed results. public query func greet(name : Text) : async Text { return "Hello, " # name # "! The count is " # Nat.toText(count) # "."; };}What's happening here:
-
actor Counter { ... }— the whole backend is one actor. -
stable var count— your data. It lives in the variable and persists; no DB to set up. -
public func increment()— an update call that changes state. -
public query func get()— a query call that only reads, so it's cheaper and faster. -
async— calls into an actor are asynchronous; results come back as promises. -
#— string concatenation in Motoko.
You'll need
import Nat "mo:base/Nat";at the top of the file to useNat.toText. The base library ships with Motoko.
Step 2 — Deploy it to your Engine
Compile and deploy your backend to a Cloud Engine:
[FILL IN: build/deploy command — e.g. opencloud deploy main.mo][FILL IN: confirm whether the CLI compiles .mo directly, or whether you build a signed .icp file first — if the latter, link to "Deploy a Signed .icp App File to Your Engine"]
When the deploy finishes, the CLI returns your Engine's address/endpoint. (See: Deploy a Signed .icp App File to Your Engine)
Step 3 — Call your backend
Test the functions you just deployed:
[FILL IN: example call command, e.g. opencloud call <engine> increment][FILL IN: example call command, e.g. opencloud call <engine> greet '("Ada")']Call increment a few times, then get — the count keeps climbing. Now redeploy your code: because count is stable, the value survives the upgrade instead of resetting to zero. That's orthogonal persistence in action.
Safe upgrades: a note on stable
When you change your code and redeploy, Motoko has to move existing data into the new version. If a change would drop or corrupt stored data — say, removing a stable variable or changing its type incompatibly — the platform detects this lossy migration and warns you before it runs.
Rule of thumb: keep anything you want to survive upgrades marked stable, and review migration warnings carefully. If an upgrade does go wrong, you can roll the Engine back.
Next steps
-
Deploy a Signed
.icpApp File to Your Engine — The full deployment path. - Restore or Roll Back an Engine After a Bad Upgrade — Your safety net.
- Adjust Engine Capacity for Traffic Spikes — Once your backend is live.
[FILL IN: link to full Motoko language reference / docs]
To finalize: I need the real deploy and call commands (and whether OpenCloud compiles .mo directly or expects a pre-built signed .icp file — that determines how Step 2/3 connect to your existing deployment article). The Motoko code itself is correct and ready to publish.
That completes all three "blocker" gaps from my earlier list (node providers, CLI setup, Motoko). With these, a brand-new user can go from zero → installed → first backend deployed, and node providers finally have an entry point.
If you want to keep building, the next tier is the conceptual/medium-priority set — What Are Cycles?, Choosing a Node Provider, and Understanding Orthogonal Persistence. Want me to draft any of those?
Comments
0 comments
Please sign in to leave a comment.