Skip to content

Commit d49dccf

Browse files
Bump SDK to v0.3.0; add white paper, gaming solution, tutorial blog post
Python SDK v0.3.0: - Version bump for serialization, encapsulation fix, JSON benchmarks - 67 tests, zero dependencies New pages: - /whitepaper — email-gated technical deep-dive (lead generation) - /solutions/gaming — real-time/multiplayer state sync SEO page - /blog/building-distributed-cache-in-50-lines — hands-on tutorial Updates: - Changelog: added v0.3.0 release entry - Landing page PyPI badge: v0.2.0 → v0.3.0 - Solutions index: added gaming card - Sitemap: 35 URLs now indexed - Blog: 4 posts total 39 static pages + 5 API routes, all compile clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cc0945f commit d49dccf

10 files changed

Lines changed: 1248 additions & 3 deletions

File tree

docs/landing/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ <h1>Stop moving data.<br><span class="highlight">Start evolving it.</span></h1>
702702
<div class="badges">
703703
<a href="https://pypi.org/project/atomik-core/" class="badge">
704704
<span class="badge-dot" style="background: var(--accent);"></span>
705-
PyPI <span class="badge-val">v0.2.0</span>
705+
PyPI <span class="badge-val">v0.3.0</span>
706706
</a>
707707
<a href="https://pypi.org/project/atomik-core/" class="badge">
708708
<span class="badge-dot" style="background: var(--accent2);"></span>

software/atomik_core/atomik_core/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
SPDX-License-Identifier: Apache-2.0
3434
"""
3535

36-
__version__ = "0.2.0"
36+
__version__ = "0.3.0"
3737

3838
from atomik_core.context import AtomikContext
3939
from atomik_core.table import AtomikTable

software/atomik_core/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "atomik-core"
7-
version = "0.2.0"
7+
version = "0.3.0"
88
description = "ATOMiK delta-state algebra — O(1) state reconstruction for any processor"
99
readme = "README.md"
1010
license = "Apache-2.0"
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import type { Metadata } from "next";
2+
import Link from "next/link";
3+
import Nav from "@/components/Nav";
4+
5+
export const metadata: Metadata = {
6+
title: "Build a Distributed Cache in 50 Lines of Python — ATOMiK Blog",
7+
description:
8+
"A step-by-step tutorial: build a 3-node distributed cache with automatic convergence using ATOMiK's delta-state algebra. No consensus protocol, no leader election.",
9+
};
10+
11+
function Code({ children }: { children: string }) {
12+
return (
13+
<pre className="rounded-lg p-4 text-sm overflow-x-auto my-4" style={{ background: "#0a0a0f", border: "1px solid #1e1e2e", color: "#22d3ee", fontFamily: "'SF Mono', 'Fira Code', 'Consolas', monospace", lineHeight: 1.7 }}>
14+
<code>{children}</code>
15+
</pre>
16+
);
17+
}
18+
19+
export default function DistributedCachePost() {
20+
return (
21+
<div className="min-h-screen" style={{ background: "#0a0a0f", color: "#e0e0e8" }}>
22+
<Nav active="Blog" />
23+
24+
<article className="max-w-3xl mx-auto px-6 pt-16 pb-24">
25+
<div className="mb-12">
26+
<Link href="/blog" className="text-sm mb-6 inline-block hover:underline" style={{ color: "#4f8fff" }}>&larr; Back to blog</Link>
27+
<time className="block text-sm font-mono mb-3" style={{ color: "#8888a0" }}>March 16, 2026</time>
28+
<h1 className="text-3xl font-bold tracking-tight mb-4 leading-tight">
29+
Build a Distributed Cache in 50 Lines of Python
30+
</h1>
31+
<div className="flex gap-2">
32+
{["tutorial", "python", "distributed-systems"].map((tag) => (
33+
<span key={tag} className="text-xs px-2 py-0.5 rounded-full" style={{ background: "rgba(34, 211, 238, 0.1)", color: "#22d3ee", border: "1px solid rgba(34, 211, 238, 0.2)" }}>{tag}</span>
34+
))}
35+
</div>
36+
</div>
37+
38+
<div className="space-y-6 text-base leading-relaxed" style={{ color: "#c8c8d4" }}>
39+
<p>
40+
Traditional distributed caches need leader election, consensus rounds, and
41+
conflict resolution. With ATOMiK, you can build a 3-node cache where writes
42+
from any node converge automatically — in about 50 lines of Python.
43+
</p>
44+
45+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Setup</h2>
46+
<Code>{`pip install atomik-core`}</Code>
47+
48+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Step 1: Create the cache node</h2>
49+
<p>Each node maintains its own <code style={{ color: "#22d3ee" }}>DeltaStream</code> — a collection of delta-state contexts indexed by address.</p>
50+
<Code>{`from atomik_core import DeltaStream
51+
52+
class CacheNode:
53+
def __init__(self, node_id: str):
54+
self.node_id = node_id
55+
self.stream = DeltaStream()
56+
self.peers: list["CacheNode"] = []
57+
58+
def connect(self, peer: "CacheNode"):
59+
self.peers.append(peer)
60+
peer.peers.append(self)`}</Code>
61+
62+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Step 2: Write = LOAD + broadcast</h2>
63+
<p>
64+
When a node writes a new value, it LOADs the value locally and broadcasts
65+
the delta to all peers. The delta is just 8 bytes — the XOR difference.
66+
</p>
67+
<Code>{` def put(self, key: int, value: int):
68+
"""Write a value and broadcast the delta."""
69+
old = self.stream.read(key)
70+
self.stream.load(key, value)
71+
delta = old ^ value # XOR delta
72+
# Broadcast to peers
73+
for peer in self.peers:
74+
peer.receive_delta(key, delta)`}</Code>
75+
76+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Step 3: Receive = ACCUM</h2>
77+
<p>
78+
When a peer receives a delta, it accumulates it. XOR is commutative —
79+
the order deltas arrive doesn&apos;t matter. Every node converges to the same state.
80+
</p>
81+
<Code>{` def receive_delta(self, key: int, delta: int):
82+
"""Apply a delta from a peer."""
83+
self.stream.accum(key, delta)
84+
85+
def get(self, key: int) -> int:
86+
"""Read the current value."""
87+
return self.stream.read(key)`}</Code>
88+
89+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Step 4: Wire it up</h2>
90+
<Code>{`# Create 3 nodes
91+
a = CacheNode("A")
92+
b = CacheNode("B")
93+
c = CacheNode("C")
94+
95+
# Full mesh topology
96+
a.connect(b)
97+
a.connect(c)
98+
b.connect(c)
99+
100+
# Initialize all nodes with the same reference
101+
for node in [a, b, c]:
102+
node.stream.load(0, 0xCAFEBABE)
103+
104+
# Node A writes a new value
105+
a.put(0, 0xDEADBEEF)
106+
107+
# All nodes converge — no consensus needed
108+
assert a.get(0) == 0xDEADBEEF
109+
assert b.get(0) == 0xDEADBEEF
110+
assert c.get(0) == 0xDEADBEEF
111+
print("All 3 nodes converged!")`}</Code>
112+
113+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Why it works</h2>
114+
<p>The magic is XOR commutativity. When Node A writes <code style={{ color: "#22d3ee" }}>0xDEADBEEF</code> to a slot that held <code style={{ color: "#22d3ee" }}>0xCAFEBABE</code>, the delta is:</p>
115+
<Code>{`delta = 0xCAFEBABE ^ 0xDEADBEEF = 0x14531455`}</Code>
116+
<p>
117+
Nodes B and C each accumulate this delta. Since <code style={{ color: "#22d3ee" }}>reference XOR accumulator = current_state</code>, they reconstruct the same value:
118+
</p>
119+
<Code>{`0xCAFEBABE ^ 0x14531455 = 0xDEADBEEF ✓`}</Code>
120+
<p>
121+
If multiple nodes write simultaneously, deltas compose. Node B writes to
122+
key 1 while Node C writes to key 2 — both deltas propagate and apply
123+
independently. No conflicts, no resolution logic, no coordinator.
124+
</p>
125+
126+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Concurrent writes to the same key</h2>
127+
<p>
128+
What happens if A and B both write to key 0 at the same time? Both deltas
129+
propagate to all nodes. The final state is deterministic — it&apos;s the XOR of
130+
both deltas applied to the reference. The &quot;last writer wins&quot; semantic is
131+
replaced by &quot;all writers compose&quot; — which is correct for many workloads
132+
(counters, flags, accumulated state).
133+
</p>
134+
<p>
135+
For workloads where you need last-writer-wins, use <code style={{ color: "#22d3ee" }}>SWAP</code>
136+
to create epochs — each SWAP resets the accumulator and promotes the current
137+
state to the new reference.
138+
</p>
139+
140+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>Add wire serialization</h2>
141+
<p>
142+
In v0.3.0, <code style={{ color: "#22d3ee" }}>DeltaMessage</code> gained
143+
compact wire format support:
144+
</p>
145+
<Code>{`from atomik_core import DeltaMessage
146+
147+
# On sender
148+
msg = DeltaMessage(addr=0, delta=0x14531455, seq=1)
149+
wire = msg.to_bytes() # 16 bytes, network byte order
150+
151+
# On receiver
152+
msg = DeltaMessage.from_bytes(wire)
153+
stream.accum(msg.addr, msg.delta)`}</Code>
154+
155+
<h2 className="text-2xl font-bold pt-4" style={{ color: "#e0e0e8" }}>What you get</h2>
156+
<ul className="list-disc pl-6 space-y-2">
157+
<li><strong>Zero coordination.</strong> No leader election, no consensus rounds, no distributed locks.</li>
158+
<li><strong>8 bytes per update.</strong> Regardless of the value size, the delta is always 8 bytes.</li>
159+
<li><strong>O(1) everything.</strong> Write, read, and sync are all constant-time.</li>
160+
<li><strong>Automatic convergence.</strong> All nodes reach the same state regardless of message ordering.</li>
161+
<li><strong>Proven correct.</strong> 92 Lean4 theorems guarantee the algebra works.</li>
162+
</ul>
163+
164+
<div className="rounded-xl border p-8 mt-8 text-center" style={{ background: "#12121a", borderColor: "#1e1e2e" }}>
165+
<h3 className="text-xl font-bold mb-3">Try it yourself</h3>
166+
<Code>{`pip install atomik-core
167+
python -c "
168+
from atomik_core import DeltaStream
169+
s = DeltaStream()
170+
s.load(0, 0xCAFEBABE)
171+
s.accum(0, 0x14531455)
172+
print(f'State: 0x{s.read(0):08x}')
173+
"`}</Code>
174+
<div className="flex flex-wrap justify-center gap-4 mt-6">
175+
<Link href="/demo" className="px-6 py-2.5 rounded-lg text-sm font-semibold" style={{ background: "#4f8fff", color: "#fff" }}>Interactive Demo</Link>
176+
<Link href="/docs/quickstart" className="px-6 py-2.5 rounded-lg text-sm font-semibold" style={{ background: "transparent", color: "#e0e0e8", border: "1px solid #1e1e2e" }}>Full Documentation</Link>
177+
</div>
178+
</div>
179+
</div>
180+
</article>
181+
</div>
182+
);
183+
}

website/src/app/blog/page.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ export const metadata: Metadata = {
99
};
1010

1111
const posts = [
12+
{
13+
slug: "building-distributed-cache-in-50-lines",
14+
title: "Build a Distributed Cache in 50 Lines of Python",
15+
date: "March 16, 2026",
16+
excerpt:
17+
"Step-by-step tutorial: 3-node distributed cache with automatic convergence. No consensus protocol, no leader election, no conflict resolution — just XOR.",
18+
tags: ["tutorial", "python", "distributed-systems"],
19+
},
1220
{
1321
slug: "atomik-vs-event-sourcing",
1422
title: "ATOMiK vs Event Sourcing: When XOR Beats Append-Only Logs",

website/src/app/changelog/page.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ type Release = {
2020
};
2121

2222
const releases: Release[] = [
23+
{
24+
version: "v0.3.0",
25+
title: "Python SDK — Serialization & Tracing",
26+
date: "March 16, 2026",
27+
category: "software",
28+
items: [
29+
"DeltaMessage serialization: to_dict/from_dict + to_bytes/from_bytes (16-byte wire format)",
30+
"Fingerprint encapsulation fix: no more direct _accumulator access",
31+
"Benchmark --json flag for CI pipeline integration",
32+
"All bench_* functions return structured result dicts",
33+
"67 tests passing (up from 60)",
34+
"pip install atomik-core==0.3.0",
35+
],
36+
},
2337
{
2438
version: "v0.4.0",
2539
title: "Kernel Module",

website/src/app/sitemap.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export default function sitemap(): MetadataRoute.Sitemap {
1313
{ url: `${baseUrl}/blog/announcing-atomik-kernel-module`, lastModified: new Date("2026-03-15"), changeFrequency: "monthly", priority: 0.7 },
1414
{ url: `${baseUrl}/blog/fpga-journey-13-dollar-chip`, lastModified: new Date("2026-03-15"), changeFrequency: "monthly", priority: 0.7 },
1515
{ url: `${baseUrl}/blog/atomik-vs-event-sourcing`, lastModified: new Date("2026-03-16"), changeFrequency: "monthly", priority: 0.7 },
16+
{ url: `${baseUrl}/blog/building-distributed-cache-in-50-lines`, lastModified: new Date("2026-03-16"), changeFrequency: "monthly", priority: 0.7 },
17+
{ url: `${baseUrl}/whitepaper`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.8 },
1618
{ url: `${baseUrl}/solutions`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.8 },
19+
{ url: `${baseUrl}/solutions/gaming`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.8 },
1720
{ url: `${baseUrl}/solutions/distributed-systems`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.8 },
1821
{ url: `${baseUrl}/solutions/iot-edge`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.8 },
1922
{ url: `${baseUrl}/solutions/financial`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.8 },

0 commit comments

Comments
 (0)