Design Philosophy
Every language embodies the values of whoever was stubborn enough to build it. Adama is no exception. Understanding the philosophy helps you work with the grain of the language rather than fighting it -- and trust me, fighting it is no fun.
Origin: Board Games
Adama was born from a very specific frustration: I wanted to bring complex board games online. Not tic-tac-toe. Games like Battlestar Galactica -- games with hidden roles, secret hands, complex turn structures, and sessions that last for hours.
Traditional web technologies just fall apart for these games:
- State complexity: A board game's state cannot be represented by a simple REST API
- Turn-based logic: "Whose turn is it and what can they do?" requires a state machine
- Secrets: Some information must be hidden from some players
- Durability: A six-hour game cannot be lost to a server restart
- Real-time updates: Players need to see changes as they happen
The name "Adama" comes from a beloved Lamancha goat that I raised. When the goat passed away, I named the programming language in his memory.
These requirements forced a fundamental rethinking of how to build multiplayer software. I couldn't just bolt real-time onto an existing framework; the whole model was wrong. What came out was a language where:
- State and compute are unified
- Privacy is a first-class concern
- Persistence is automatic
- Real-time sync is built in
- State machines are natural
While board games were the origin, Adama's approach applies broadly to any application where people share state in real-time. The board game constraints turned out to be a gift -- they forced good design.
The Living Document Paradigm
Most documents in computers are dead. Consider a JSON file sitting in storage:
{
"name": "Jeff",
"state": "Washington",
"title": "Dark Lord"
}
This document will never change on its own. It requires external forces -- programs, APIs, users -- to modify it. It just sits there, inert.
Adama introduces the concept of a living document: a document that can change on its own over time.
public int ticks;
@construct {
ticks = 0;
transition #tick in 1;
}
#tick {
ticks++;
transition #tick in 1;
}
This document is alive. Once created, it will count ticks every second forever. No external stimulus required.
A living document is essentially a tiny, persistent server. It maintains state across restarts, responds to messages from connected clients, executes state machine transitions over time, and replicates changes to observers. It's a little VM that wakes up, does work, and goes back to sleep.
Think of each Adama document as a microservice that is automatically persisted, automatically restarted, and automatically distributed. You focus on the logic; the platform handles the infrastructure. The beauty of this is you stop thinking about servers entirely.
This paradigm shift -- from dead documents that need external programs to living documents that contain their own behavior -- is central to how Adama works. Once it clicks, everything else follows.
Privacy as First-Class
In traditional systems, privacy is an afterthought bolted onto the application layer. Databases store data, and application code decides who can see what. This leads to bugs, leaks, and constant vigilance. I've seen enough data exposure incidents to know that "be careful" isn't a strategy.
Adama takes a different approach: privacy is a language feature.
record Card {
public int id;
private principal owner;
viewer_is<owner> int value;
}
Every field has a visibility modifier:
| Modifier | Meaning |
|---|---|
public |
Anyone connected can see it |
private |
Only code can access it; never sent to clients |
viewer_is<field> |
Only the principal in that field can see it |
use_policy<name> |
Custom code determines visibility |
This was born directly from board game requirements. In poker, you should see your own cards but not your opponents'. In hidden-role games, some information must be secret. These aren't edge cases -- they are the core gameplay. And if you get privacy wrong, the game is broken.
record Card {
public int id;
public int value;
}
record Hand {
private principal player;
viewer_is<player> list<Card> cards;
}
table<Hand> hands;
// Each player sees only their own hand
bubble my_hand = iterate hands where player == @who;
The @who special variable refers to the current viewer. The bubble keyword creates a computation that runs per-viewer, showing each person only what they should see.
Unlike application-layer privacy checks that can be bypassed or forgotten, Adama's privacy modifiers are enforced at the language level. Data literally cannot flow to unauthorized clients. The compiler won't let it.
This model extends way beyond games. Medical records, financial information, personal preferences -- anything where per-user data matters benefits from compile-time privacy guarantees rather than "I hope the middleware caught that."
Affordability by Design
Cloud computing has created an illusion that infrastructure is cheap. A $5/month virtual machine seems trivial. But think about it:
- What happens when the $5 machine needs to be upgraded?
- What is the human cost of maintaining that machine?
- What happens when revenue dips below operational costs?
- What happens to games and applications when companies shut down?
I designed Adama with long-term economics in mind because I want the things people build to survive.
The Math of Permanence
Consider Amazon S3 storage costs. At $0.023/GB/month, with a pessimistic 1% annual return, an upfront payment of roughly $28 could keep one gigabyte alive forever. A typical board game uses perhaps 100KB of state. That's about three cents to preserve a game's state indefinitely.
Three cents. For forever. (Well, forever-ish. As long as S3 exists.)
This is only possible because Adama stores changes (deltas), not full snapshots. A game that runs for six hours might involve thousands of moves, but each move produces only a small change.
Shared Infrastructure
Adama is designed so that a single machine can host thousands of distinct documents. The platform amortizes the costs of network infrastructure, monitoring, security updates, and operational maintenance across everyone.
Individual game developers benefit from infrastructure that would be insane for them to build alone, at budgets that actually make sense for indie projects.
Consumption-Based Billing
Rather than paying for idle servers, Adama's model charges based on actual usage -- storage used, messages processed, connections maintained, bandwidth consumed. An inactive game costs nearly nothing. A popular game costs proportionally to its usage.
The aspiration is that games built on Adama could theoretically run forever -- as long as S3 exists and someone covers the minimal storage costs. I find this idea unreasonably exciting.
Laziness as Virtue
The best code is code you don't have to write. Adama embraces "laziness" as a design principle: the platform should handle everything that can be automated. I don't want to write boilerplate. I don't want you to write boilerplate. Life is too short.
What You Don't Write
With Adama, you never need to:
Serialize data
record Card {
public int id;
public int value;
}
// Just declare state - serialization is automatic
public int score;
public string player_name;
table<Card> deck;
Handle network failures
// Messages are reliably delivered or transactions roll back
message Move {
int x;
int y;
}
channel make_move(Move m) {
// If anything fails, the document state is unchanged
}
Manage persistence
// Every change is automatically durable
@construct {
// This state survives server restarts
}
Synchronize state
record Player {
public int id;
public string name;
}
table<Player> players;
// Changes automatically flow to connected clients
public formula player_count = (iterate players).size();
Build polling mechanisms
// Real-time updates are built in
@connected {
// Clients receive updates as they happen
return true;
}
The Excel Inspiration
Excel is one of the most productive programming environments ever created. Non-programmers build complex financial models, simulations, and dashboards with it. Why? Immediate feedback -- results appear as you type. No boilerplate -- you just write formulas. Automatic recalculation -- dependencies are handled for you. Data is always visible.
Adama aims to capture this productivity in a text-based language suitable for building real products. You focus on what the data should be; Adama figures out how to make it happen.
// Excel-like reactivity in code
public int x = 10;
public int y = 20;
public formula sum = x + y; // Updates automatically
public formula product = x * y; // Updates automatically
public formula both = sum + product; // Dependencies chain
Trust the Runtime
Adama's philosophy is that you should trust the runtime to handle when to persist data, how to send updates to clients, when to garbage collect unused resources, and how to recover from failures.
This trust is earned through guarantees: every committed change is durable, privacy rules are always enforced, deltas are always consistent, and replay produces identical results. The runtime does its job so you can focus on yours.
The more you delegate to the runtime, the less code you write, the fewer bugs you have, and the more reliable your application becomes. Fight the urge to control everything -- let Adama handle the plumbing.
Now that you understand why Adama was designed this way, learn how it actually works under the hood in How It Works.