Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
CRDTs - The science behind Phoenix Presence
Search
Maciej Kaszubowski
May 25, 2017
Programming
2
260
CRDTs - The science behind Phoenix Presence
Maciej Kaszubowski
May 25, 2017
Tweet
Share
More Decks by Maciej Kaszubowski
See All by Maciej Kaszubowski
Error-free Elixir
mkaszubowski
0
330
Modular Design in Elixir (ElixirConf EU 2019)
mkaszubowski
2
720
The Big Ball of Nouns
mkaszubowski
0
97
Modular Design in Elixir
mkaszubowski
1
380
Our three years with Elixir
mkaszubowski
0
240
Concurrency Basics for Elixir
mkaszubowski
0
120
Distributed Elixir
mkaszubowski
0
150
Software Architecture
mkaszubowski
0
130
Let it crash - fault tolerance in Elixir/OTP
mkaszubowski
0
470
Other Decks in Programming
See All in Programming
Flutterで備える!Accessibility Nutrition Labels完全ガイド
yuukiw00w
0
170
What's new in AppKit on macOS 26
1024jp
0
150
MDN Web Docs に日本語翻訳でコントリビュートしたくなる
ohmori_yusuke
1
130
#QiitaBash MCPのセキュリティ
ryosukedtomita
1
1.5k
AI駆動のマルチエージェントによる業務フロー自動化の設計と実践
h_okkah
0
230
Startups on Rails in Past, Present and Future–Irina Nazarova, RailsConf 2025
irinanazarova
0
250
LT 2025-06-30: プロダクトエンジニアの役割
yamamotok
0
870
AIエージェントはこう育てる - GitHub Copilot Agentとチームの共進化サイクル
koboriakira
0
760
Git Sync を超える!OSS で実現する CDK Pull 型デプロイ / Deploying CDK with PipeCD in Pull-style
tkikuc
4
350
TypeScriptでDXを上げろ! Hono編
yusukebe
3
770
AIともっと楽するE2Eテスト
myohei
8
3k
リバースエンジニアリング新時代へ! GhidraとClaude DesktopをMCPで繋ぐ/findy202507
tkmru
3
970
Featured
See All Featured
Practical Orchestrator
shlominoach
189
11k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
The Power of CSS Pseudo Elements
geoffreycrofte
77
5.9k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
How to Ace a Technical Interview
jacobian
278
23k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
340
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.4k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Facilitating Awesome Meetings
lara
54
6.5k
YesSQL, Process and Tooling at Scale
rocio
173
14k
Side Projects
sachag
455
42k
Transcript
The Problem
None
Server Node 1 Server Node 2
Node A Node B [User] [User] [User] [] [] [User]
User connects User disconnects
There's no global time
Node A Node B [User] [User] [User] [] [] [User]
User connects User disconnects
Node A Node B [User] [User] [User] [] [] [User]
User connects User disconnects
Node A Node B
P.track(self, "users", "U1", %{})
P.track(self, "users", "U1", %{}) P.list("users") %{"U1" %{metas: [%{phx_ref: "…"}]}}
P.track(self, "users", "U1", %{}) P.list("users") P.track(self, "users", "U2", %{}) %{"U1"
%{metas: [%{phx_ref: "…"}]}}
P.track(self, "users", "U1", %{}) P.list("users") P.track(self, "users", "U2", %{}) P.list("users")
%{"U1" %{metas: [%{phx_ref: "…"}]}, "U2" %{metas: [%{phx_ref: "…"}]}} %{"U1" %{metas: [%{phx_ref: "…"}]}}
P.track(self, "users", "U1", %{}) P.list("users") P.track(self, "users", "U2", %{}) P.list("users")
%{"U1" %{metas: [%{phx_ref: "…"}]}, "U2" %{metas: [%{phx_ref: "…"}]}} P.track(self, "users", "U1", %{}) P.untrack(self, "users", "U1") %{"U1" %{metas: [%{phx_ref: "…"}]}}
P.track(self, "users", "U1", %{}) P.list("users") P.track(self, "users", "U2", %{}) P.list("users")
%{"U1" %{metas: [%{phx_ref: "…"}]}, "U2" %{metas: [%{phx_ref: "…"}]}} P.track(self, "users", "U1", %{}) P.untrack(self, "users", "U1") P.list("users") %{"U1" %{metas: [%{phx_ref: "…"}]}, "U2" %{metas: [%{phx_ref: "…"}]}} P.list("users") %{"U1" %{metas: [%{phx_ref: "…"}]}, "U2" %{metas: [%{phx_ref: "…"}]}} %{"U1" %{metas: [%{phx_ref: "…"}]}}
CRDTs The science behind Phoenix Presence Maciej Kaszubowski
Conflict-free Replicated Data Type
Alternatives
• Single source of truth (DB) • Consensus algorithm •
Resolving conflicts manually
Why CRDTs?
Eventually consistent Highly available Easy to use
Eventually consistent Highly available Easy to use Hard to create
:(
Features
1. Commutative 2. Associative 3. Idempotent x y = y
x (x y) z = x (y z) x x = x
Server Node 1 Server Node 2 Server Node 3
Client Client Client Client Client Client Client Client Client Server
Examples
Counters
Node A Node B +5 5 8 -2 3 +5
User connects User disconnects 0 0 5 3 8
Node A Node B +5 5 8 -2 8 +5
User connects User disconnects 0 0 5 3 13 10
G-Counter Grow-only counter
Node 2: 3 Value=8 Node 1: 5 Node 3: 1
Merge
Node 2: 3 Value=9 Node 1: 6 Node 3: 1
+1 Merge
PN-Counter Positive-Negative Counter
Node 2: P=2 N=2 Value=7 Node 1: P=5 N=2 Node
3: P=4 N=0 3 0 4 Merge
Node 2: P=2 N=2 Value=6 Node 1: P=5 N=3 Node
3: P=4 N=0 2 0 4 +1 Merge
Node 2: P=2 N=2 Value=8 Node 1: P=5 N=3 Node
3: P=6 N=0 2 0 6 +2 +1 Merge
Sets
Node A Node B [User] [User] [User] [] [] [User]
User connects User disconnects
G-Set Grow-only set
Node 2: [1,2] Value=[1,2,3,4] Node 1: [1] Node 3: [3,4]
Merge
Node 2: [1,2] Value=[1,2,3,4,5] Node 1: [1,5] Node 3: [3,4]
Merge
2P-Set Two-phase set
Node 2: [1,2],[] Value=[1,2,3,4] Node 1: [1],[] Node 3: [3,4],[]
Merge
Node 2: [1,2],[] Value=[1,2,3,4] Node 1: [1],[] Node 3: [3,4],[]
Merge G-Set for adds
Node 2: [1,2],[] Value=[1,2,4] Node 1: [1],[] Node 3: [3,4],[3]
Merge G-Set for removals
Elements cannot be re-added
Removes win
Node A Node B [ ] Add Remove [1] [
] [1]
Node A Node B [ ] [1] Add Remove [1]
[1] [ ] [1] [ ] [1]
Node A Node B [ ] [1] Add Remove [1]
[1] [ ] [1] [ ] [1]
Node A Node B [ ] [1] [1] Add Remove
[1] [1] [1] [ ] [1] [1] [1] [ ] [1]
OR-Set Observed-remove set
Node A Node B [ ] Add Remove [{A,1}] [
] [{A,1}]
Node A Node B [ ] [ ] Add Remove
[{A,1}] [{A,1}] [ ] [ ] [{A,1}] [{A,1}, ]
Node A Node B [ ] [ 1 ] Add
Remove [{A,1}] [{A,1}] [ ] [ ] [{A,1}] [{A,1},{A,2}]
Node A Node B [ ] [ 1 ] Add
Remove [{A,1}] [{A,1}] [ ] [ ] [{A,1}] [{A,1},{A,2}]
Node A Node B [ ] [ 1 ] Add
Remove [{A,1}] [{A,1}] [ ] [ ] [{A,1}] [{A,1},{A,2}] [ 1 ] [{A,1},{A,2}] [{A,1},{A,2}] [ 1 ]
Node A Node B [ ] [ 1 ] Add
Remove [{A,1}] [{A,1}] [ ] [ ] [{A,1}] [{A,1},{A,2}] [ 1 ] [{A,1},{A,2}] [{A,1},{A,2}] [ 1 ] [A] [A]
Add 1000 Remove 1000 Add Remove …
ORSWOT Observed-remove set without tombstones
None
None
Use Cases
None
None
None
None
• Load balancing / routing • Mobile clients synchronisation •
Temporary data on the servers • Avoiding work duplication • Collaborative editing
None
lasp-lang.readme.io
Summary
You're (almost) always designing a distributed system
Think about failures
Choose the correct tool for the job
References • https://medium.com/@istanbul_techie/a-look-at-conflict-free-replicated-data- types-crdt-221a5f629e7e • http://basho.com/posts/technical/distributed-data-types-riak-2-0/ • http://highscalability.com/blog/2014/10/13/how-league-of-legends-scaled- chat-to-70-million-players-it-t.html •
https://hal.inria.fr/inria-00609399v1/document • https://developers.soundcloud.com/blog/roshi-a-crdt-system-for- timestamped-events
Thanks!