Menu

Connect

๐Ÿ“ Post

Liquid Democracy: Building Transparent Delegation Systems

governancedemocracyalgorithmsweb3graph-theory
By Ryan Cwynarโ€ขโ€ข5 min read

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:

  1. Vote directly on the issue
  2. 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:

  1. Find all direct votes
  2. For each delegator, traverse the chain until you find a direct vote
  3. 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:

  1. Delegation graph is public: Everyone can see who delegates to whom
  2. Votes are auditable: You can trace exactly how your vote was used
  3. 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:

  1. Graph database (or just PostgreSQL with recursive CTEs)
  2. Real-time subscriptions for delegation changes
  3. Audit log for every vote resolution
  4. 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