Democracy has a scaling problem. Direct democracy works great for small groupsโeveryone votes on everything. But it doesn't scale. Representative democracy scales, but you lose agency. You vote once every few years and hope for the best.
Liquid democracy is a third way. And it's surprisingly simple to implement.
The Core Concept
In liquid democracy, you have two choices for any decision:
- Vote directly on the issue
- Delegate your vote to someone you trust
The magic: delegation is transitive. If Alice delegates to Bob, and Bob delegates to Carol, Alice's vote goes to Carol. It's a directed graph.
Alice โ Bob โ Carol
โ
Dave
Carol now has 3 votes: her own, plus Bob's (which includes Alice's and Dave's).
Why It's Powerful
Flexibility: Delegate to different people for different topics. Your economist friend handles fiscal policy. Your doctor friend handles healthcare.
Accountability: Delegates can't hide. Their votes are public. If they vote against your interests, you can see it and re-delegate.
Scalability: You don't need to research every issue. Trust experts in their domains.
The Data Structure
At its core, liquid democracy is a directed graph:
interface Voter {
id: string;
delegate?: string; // who I delegate to (optional)
}
interface Vote {
voterId: string;
proposalId: string;
choice: 'yes' | 'no' | 'abstain';
}
interface Delegation {
from: string;
to: string;
topic?: string; // optional topic-scoping
weight: number; // usually 1, but could be fractional
}
Counting Votes: Graph Traversal
When tallying votes, you need to:
- Find all direct votes
- For each delegator, traverse the chain until you find a direct vote
- Add their weight to that vote
function countVotes(proposalId: string): { yes: number; no: number } {
const directVotes = getDirectVotes(proposalId);
const result = { yes: 0, no: 0 };
for (const voter of allVoters) {
const finalVote = resolveVote(voter.id, proposalId);
if (finalVote) {
result[finalVote.choice]++;
}
}
return result;
}
function resolveVote(voterId: string, proposalId: string): Vote | null {
// Check for direct vote
const direct = getDirectVote(voterId, proposalId);
if (direct) return direct;
// Follow delegation chain
const delegate = getDelegate(voterId);
if (!delegate) return null; // abstain
return resolveVote(delegate, proposalId); // recursive
}
The Cycle Problem
What if Alice โ Bob โ Carol โ Alice? Infinite loop.
function resolveVote(voterId: string, proposalId: string, visited = new Set<string>()): Vote | null {
if (visited.has(voterId)) {
return null; // cycle detected, treat as abstain
}
visited.add(voterId);
const direct = getDirectVote(voterId, proposalId);
if (direct) return direct;
const delegate = getDelegate(voterId);
if (!delegate) return null;
return resolveVote(delegate, proposalId, visited);
}
Or better: prevent cycles at delegation time.
Transparency: The Killer Feature
In traditional representative democracy, you don't know how your representative voted until after the fact (if ever).
In liquid democracy with transparency:
- Delegation graph is public: Everyone can see who delegates to whom
- Votes are auditable: You can trace exactly how your vote was used
- Real-time updates: Retract delegation instantly if you disagree
interface DelegationAudit {
originalVoter: string;
delegationChain: string[]; // [Alice, Bob, Carol]
finalVote: Vote;
timestamp: number;
}
// "Alice's vote was cast by Carol as 'yes' via Bob"
Topic-Scoped Delegation
One delegate for everything is limiting. Topic scoping fixes this:
interface TopicDelegation {
from: string;
to: string;
topic: 'fiscal' | 'healthcare' | 'environment' | 'general';
}
// Alice delegates:
// - fiscal โ her economist friend
// - healthcare โ her doctor friend
// - general โ her politically-savvy friend
When resolving votes, check topic-specific delegation first, then fall back to general.
The UI Challenge
The hardest part isn't the algorithmโit's making it understandable.
Users need to see:
- Who they're currently delegating to (by topic)
- How their delegate voted recently
- The full delegation graph (who's influential?)
- Alerts when their delegate votes on something
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Your Delegations โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ๐ฆ Fiscal Policy โ @economist_jane โ
โ Last vote: "Budget Amendment" โ Yes
โ โ
โ ๐ฅ Healthcare โ @dr_smith โ
โ Last vote: "Insurance Reform" โ No
โ โ
โ ๐ General โ @trusted_friend โ
โ Last vote: None this week โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Building It
I'm working on an open-source implementation. Key components:
- Graph database (or just PostgreSQL with recursive CTEs)
- Real-time subscriptions for delegation changes
- Audit log for every vote resolution
- Topic taxonomy that's flexible but not overwhelming
The goal: a governance system for DAOs, communities, or any group that wants to scale decision-making without sacrificing individual agency.
Why Now?
Blockchain made trustless voting possible. AI makes research feasible. The infrastructure for liquid democracy finally exists.
We've been stuck with 18th-century democracy in a 21st-century world. Time to upgrade.
Interested in liquid democracy implementations? I'm building one. Let's talk: LinkedIn