Clone
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Elixir in the Real World — GR Web Dev Meetup</title>
<link rel="stylesheet" href="https://unpkg.com/reveal.js@5.1.0/dist/reset.css" />
<link rel="stylesheet" href="https://unpkg.com/reveal.js@5.1.0/dist/reveal.css" />
<link rel="stylesheet" href="https://unpkg.com/reveal.js@5.1.0/dist/theme/white.css" id="theme" />
<link rel="stylesheet" href="https://unpkg.com/reveal.js@5.1.0/plugin/highlight/monokai.css" />
<link rel="stylesheet" href="shared.css" />
</head>
<body>
<div class="reveal">
<div class="slides">
<!-- SLIDE 1: Title -->
<section data-transition="fade">
<h1>Elixir in the Real World</h1>
<img src="elixir-logo.svg" alt="Elixir" style="height: 120px; margin: 0.3em 0;" />
<p class="subtitle">A Practical Introduction</p>
<p class="meta">
<strong>Torey Heinz</strong><br />
GR Web Dev Meetup — February 23, 2026
</p>
<aside class="notes">
Welcome to Elixir in the Real World, A Practical Introduction.<br>
I'll share why Elixir is awesome, a quick intro to the language, and what it looks like in production.
</aside>
</section>
<!-- SLIDE 2: About Me -->
<section>
<h2>whoami → Torey Heinz</h2>
<img src="torey.jpg" alt="Torey Heinz" style="height: 150px; border-radius: 50%; object-fit: cover;" />
<ul>
<li class="fragment">Full-stack developer — 15+ years building web applications</li>
<li class="fragment"><strong>Vianet Management</strong> — <a href="https://www.vianetmanagement.com/">vianetmanagement.com</a></li>
<li class="fragment"><strong>Shopflow</strong> — Founder — Software for small manufacturers</li>
<li class="fragment">Started with Ruby on Rails → caught the Elixir bug</li>
</ul>
<aside class="notes">
Whoami? I've been building web applications for over 15 years, mostly with Ruby on Rails.
I work at Vianet Management here in West Michigan, and I also founded Shopflow for small manufacturing businesses.
I started with Rails and went deep with Ruby, but I caught the Elixir bug a few years ago working at Vianet and haven't looked back.
</aside>
</section>
<!-- SLIDE 3: Vianet Entities -->
<section>
<h2>Vianet Management</h2>
<p class="smaller muted">
Huge thanks to Vianet for fully embracing Elixir and giving us the freedom to adopt it across our stack.
</p>
<div class="entity-grid">
<div class="entity-card">
<img src="logos/thefactory.png" alt="The Factory" class="entity-logo" />
<div class="entity-text">
<h4>The Factory</h4>
<p>Coworking space in Grand Rapids</p>
</div>
</div>
<div class="entity-card">
<img src="logos/puppies.png" alt="Puppies.com" class="entity-logo" />
<div class="entity-text">
<h4>Puppies.com</h4>
<p>Online puppy marketplace</p>
</div>
</div>
<div class="entity-card">
<img src="logos/roommates.png" alt="Roommates.com" class="entity-logo" />
<div class="entity-text">
<h4>Roommates.com</h4>
<p>Roommate & room rental matching</p>
</div>
</div>
<div class="entity-card">
<img src="logos/orbitfour.png" alt="OrbitFour" class="entity-logo" />
<div class="entity-text">
<h4>OrbitFour</h4>
<p>Domain registrar — no upselling</p>
</div>
</div>
<div class="entity-card">
<img src="logos/reputablerooms.png" alt="Reputable Rooms" class="entity-logo" />
<div class="entity-text">
<h4>Reputable Rooms</h4>
<p>Verified room & roommate search</p>
</div>
</div>
<div class="entity-card">
<img src="logos/rentprotect.png" alt="RentProtect" class="entity-logo" />
<div class="entity-text">
<h4>RentProtect</h4>
<p>Affordable renters insurance</p>
</div>
</div>
</div>
<aside class="notes">
Vianet Management runs several businesses, all powered by Elixir in production. The Factory is a coworking space right here in GR. Puppies.com and Roommates.com are marketplaces. OrbitFour is our domain registrar — straightforward, no upselling. Reputable Rooms is for verified room rentals, and RentProtect provides affordable renters insurance. Everything you see today runs in production because Vianet was willing to invest in Elixir.
</aside>
</section>
<!-- SLIDE 4: What We're Covering -->
<section>
<h2>What We're Covering Today</h2>
<p class="muted">Three parts:</p>
<ol>
<li class="fragment"><strong>Why Elixir?</strong> — Where it comes from and why it matters</li>
<li class="fragment"><strong>The Language</strong> — Pattern matching, processes, and LiveView <em>(live demos!)</em></li>
<li class="fragment"><strong>Real-World Code</strong> — Production systems at Vianet</li>
</ol>
<p class="fragment muted" style="margin-top: 1em;">Then we'll open it up for Q&A.</p>
<aside class="notes">
Here's the roadmap. First, why Elixir exists. Then we'll do live coding in LiveBook to explore the language. Finally, real production code from Vianet. We'll save time for questions at the end.
</aside>
</section>
<!-- SLIDE 5: Section Divider — Part 1 -->
<section class="section-divider" data-transition="zoom">
<h2>Part 1: Why Elixir?</h2>
<p>Where it comes from and why you should care</p>
<aside class="notes">
Before we look at any code, let's answer the question: why does this language exist, and why should you care?
</aside>
</section>
<!-- SLIDE 6: Erlang & The BEAM -->
<section>
<h2>Erlang & The BEAM</h2>
<p>Built by <strong>Ericsson</strong> in 1986 for telecom switches — systems that literally <strong>could not go down</strong>.</p>
<p class="fragment small muted">The BEAM VM was designed from scratch for this:</p>
<ul>
<li class="fragment"><strong>Lightweight processes</strong> — ~2KB each, millions at once</li>
<li class="fragment"><strong>Per-process GC</strong> — no stop-the-world pauses</li>
<li class="fragment"><strong>Crash isolation</strong> — one process can't take down the app</li>
</ul>
<p class="fragment muted" style="margin-top: 0.8em; font-style: italic;">
Battle-tested for 40 years. 99.999999% uptime.<br/>
It just wasn't fun to work with...
</p>
<aside class="notes">
Erlang was created by Ericsson in 1986 for telecom switches — systems that literally could not go down. Think phone networks: millions of simultaneous calls, where one dropped call can't crash the whole system. The uptime target? Nine nines — about 31 milliseconds of downtime per year.<br><br>
The BEAM is the runtime, and it's fundamentally different from V8 or the JVM. Every request gets its own process — about 2KB each — millions concurrently. The scheduler is preemptive — in Node, one heavy request blocks the event loop; on the BEAM, every process gets a fair slice. GC happens per-process — no stop-the-world pauses. And crash isolation — if one request hits a bug, that process dies alone. The rest of your app doesn't notice.<br><br>
The catch? Erlang syntax is... an acquired taste. That's where Elixir comes in.
</aside>
</section>
<!-- SLIDE 8: Elixir -->
<section>
<h2>Elixir <span class="muted" style="font-weight: 400;">(2012)</span></h2>
<p><strong>José Valim</strong> — Ruby on Rails core team member — asked:</p>
<blockquote class="fragment">
“What if we took the best runtime in the world and made it a joy to write?”
</blockquote>
<ul>
<li class="fragment"><strong>Modern syntax</strong> — inspired by Ruby</li>
<li class="fragment"><strong>Excellent tooling</strong> — Mix, Hex, ExUnit</li>
<li class="fragment"><strong>Full Erlang access</strong> — 40 years of battle-tested libraries</li>
</ul>
<p class="fragment small" style="margin-top: 0.8em; color: #555;">
Elixir doesn't replace Erlang. It <strong>runs on</strong> Erlang's BEAM.
</p>
<aside class="notes">
José Valim was on the Rails core team. He saw the power of the BEAM but wanted better ergonomics. Elixir gives you all of Erlang's superpowers — concurrency, fault tolerance, distribution — with a syntax that feels like Ruby. The tooling is excellent: Mix is the build tool, Hex is the package manager, and ExUnit is the built-in test framework. And you get the entire Erlang ecosystem for free — Elixir doesn't replace Erlang, it runs on the same VM.
</aside>
</section>
<!-- SLIDE 9: Who's Using It -->
<section>
<h2>Who's Using Elixir?</h2>
<p class="small muted">Companies choose Elixir when <strong>reliability and scale actually matter</strong>.</p>
<div class="company-grid">
<div class="company-card fragment">
<img src="logos/discord.svg" alt="Discord" class="company-logo" />
<div class="company-text">
<h4>Discord</h4>
<p>5M+ concurrent users, real-time messaging</p>
</div>
</div>
<div class="company-card fragment">
<img src="logos/pinterest.svg" alt="Pinterest" class="company-logo" />
<div class="company-text">
<h4>Pinterest</h4>
<p>Notification delivery, billions of events</p>
</div>
</div>
<div class="company-card fragment">
<img src="logos/pepsi.svg" alt="Pepsi" class="company-logo" />
<div class="company-text">
<h4>Pepsi</h4>
<p>Real-time manufacturing & logistics</p>
</div>
</div>
<div class="company-card highlight fragment">
<img src="elixir-logo.svg" alt="Phoenix" class="company-logo" />
<div class="company-text">
<h4>Phoenix Demo <span class="muted" style="font-weight: 400;">(2015)</span></h4>
<p>2M simultaneous WebSocket connections on a single server</p>
</div>
</div>
</div>
<aside class="notes">
This isn't a hobby language. Discord handles 5 million concurrent users with Elixir. Pinterest processes billions of notification events. Pepsi runs real-time manufacturing monitoring. And the famous Phoenix benchmark: 2 million simultaneous WebSocket connections on ONE server. That's the BEAM in action. And of course, Vianet Management, right here in West Michigan.
</aside>
</section>
<!-- SLIDE 10: Why It Matters — I/O bound insight -->
<section data-auto-animate>
<h2>Why It Matters for Web Apps</h2>
<ul>
<li class="fragment"><strong>Concurrency</strong> — web apps are I/O bound; most time is spent waiting on databases, APIs, file systems</li>
<li class="fragment"><strong>Fault tolerance</strong> — processes crash in isolation, supervisors auto-restart them</li>
<li class="fragment"><strong>Real-time built in</strong> — WebSockets via Phoenix Channels & LiveView, no extra infrastructure</li>
<li class="fragment"><strong>Background jobs built in</strong> — native processes + Oban replace Redis + Sidekiq/Bull</li>
</ul>
<aside class="notes">
Web apps are I/O bound — most time is spent waiting on databases and APIs. The BEAM was built for exactly this. But it's not just concurrency. Fault tolerance means one bad request doesn't crash your app — supervisors restart failed processes automatically. Real-time is built right in with Phoenix Channels and LiveView — no Redis pub/sub or Socket.io needed. And background processing? The BEAM lets you spin up lightweight processes for things like rate limiters and caches right in your app. For persistent job queues — retries, scheduling, prioritization — there's Oban, backed by Postgres. No Redis required. It replaces what you'd use Sidekiq or Bull for.
</aside>
</section>
<!-- SLIDE 14: Let's Dive In -->
<section class="section-divider" data-transition="zoom">
<h2>Let's Dive In</h2>
<p>Now that you know <strong>why</strong> Elixir exists and <strong>who</strong> is using it,<br/>let's look at <strong>what makes it different</strong>.</p>
<p style="margin-top: 1em; font-size: 0.9em;">
Next up: <strong>The Language</strong> — pattern matching, processes, and LiveView
</p>
<aside class="notes">
Alright, that's the "why." Now let's switch over to LiveBook and get hands-on with the language. We'll look at pattern matching, processes, supervision, and LiveView — all with live, runnable code.
</aside>
</section>
</div>
</div>
<script src="https://unpkg.com/reveal.js@5.1.0/dist/reveal.js"></script>
<script src="https://unpkg.com/reveal.js@5.1.0/plugin/highlight/highlight.js"></script>
<script src="https://unpkg.com/reveal.js@5.1.0/plugin/notes/notes.js"></script>
<script src="https://unpkg.com/reveal.js@5.1.0/plugin/markdown/markdown.js"></script>
<script>
Reveal.initialize({
hash: true,
transition: 'slide',
slideNumber: true,
plugins: [RevealHighlight, RevealNotes, RevealMarkdown],
highlight: {
highlightOnLoad: true
}
});
</script>
</body>
</html>