🔥 From Zero to Serverless: Building a Real-Time Chat App with Deno, WebSockets, and No Backend
Imagine building a real-time chat application where there's no traditional backend—no Express, no database, not even a VM running 24/7. Sounds crazy? Welcome to the world of Deno and serverless WebSockets.
In this article, we’re diving deep into a lesser-known yet powerful use case: spinning up a real-time chat system using Deno Deploy, native WebSockets, and entirely stateless architecture. This is not your normal CRUD + PostgreSQL tutorial—this is an architectural eye-opener for modern developers.
🤯 Why This Setup Matters
Most chat apps are built on socket.io with Express or Nest.js, tethered to a server and a database with sessions, user tokens, etc. But what if:
- You didn’t need an always-on server?
- Your app scaled instantly under traffic?
- You never paid for idle?
- You didn’t even need a database for transient messages?
You can use Deno Deploy + WebSockets + Edge broadcast channels to build a chat app that’s instantly scalable and runs at the edge. Welcome to the serverless revolution.
🛠️ Tech Stack
- Deno Deploy - Serverless JavaScript/TypeScript runtime.
- Native WebSockets - Real-time communication.
- BroadcastChannel API - Native API to synchronise between edge locations (yes, stateless side channel!)
- Vanilla HTML/JS frontend
🎯 What We'll Build
A real-time chat app:
- Send/receive messages instantly
- No backend
- Client-side rendered
- Completely stateless (no DB!)
⚡ Quick Preview
📦 Getting Started
1. Project Structure
chat-app/
├── main.ts # Deno serverless handler
└── static/
└── index.html # UI
🧠 The Magic in main.ts
// main.ts
import { serve } from "https://deno.land/std@0.202.0/http/server.ts";
// Broadcast channel to relay messages across edge instances
const channel = new BroadcastChannel("global-chat");
serve((req) => {
const { socket, response } = Deno.upgradeWebSocket(req);
socket.onopen = () => {
console.log("Client connected");
};
socket.onmessage = (event) => {
const msg = event.data;
// Broadcast to all edges / users
channel.postMessage(msg);
};
// Relay messages to connected clients
channel.onmessage = (e) => {
socket.send(e.data);
};
socket.onclose = () => console.log("Client disconnected");
return response;
});
Deploy it Now
You can instantly deploy this with:
deno deploy --project=chat-app main.ts
💻 Frontend (index.html)
<!-- static/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Deno Chat</title>
<style>
body { font-family: sans-serif; margin: 1rem; }
#messages { height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 1rem; }
input { width: 80%; }
</style>
</head>
<body>
<h2>💬 Deno Real-Time Chat</h2>
<div id="messages"></div>
<input id="messageInput" placeholder="Type a message..." />
<button onclick="sendMessage()">Send</button>
<script>
const ws = new WebSocket("wss://your-deno-project.deno.dev");
const messagesDiv = document.getElementById("messages");
ws.onmessage = (event) => {
const el = document.createElement("div");
el.textContent = event.data;
messagesDiv.appendChild(el);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
};
window.sendMessage = () => {
const input = document.getElementById("messageInput");
if (input.value) ws.send(input.value);
input.value = "";
};
</script>
</body>
</html>
🧪 Curious Edge Tech: The Broadcast Channel
Deno Deploy has support for BroadcastChannel, which is essentially a real-time communication tunnel across Deno's global edge locations.
This is the key. Since your WebSocket connections might hit different edge servers, a local in-memory relay won’t work. But with BroadcastChannel, messages get broadcast to all connected edge nodes, creating true global state synchronization—without Redis or databases.
🌍 Real-Life Use Cases
- Live score update apps
- Real-time dashboards
- Multiplayer browser games
- Temporary real-time community chats (like Reddit AMAs)
🤔 What’s Missing (and Why That’s Okay)
This app is great for use cases where message history is ephemeral. Think more WhatsApp group live than Slack workspace. If you need persistence:
- Add Supabase/PlanetScale/Fauna for DB storage.
- Store messages on the client with IndexedDB.
But if your messages can vanish after reload, you just built a beautiful stateless chat system, instantly scalable, with no backend code beyond a single file. Pretty cool, huh?
🚀 Next Steps
- Deploy this app on https://deno.com/deploy
- Add localStorage to cache messages client-side
- Add usernames, emojis, and typing indicators
- Add authentication using Deno KV (Redis-like storage)
🧠 Lessons Learned
✅ WebSockets are amazing — and native everywhere now
✅ Deno Deploy lets you build at the edge without thinking about servers
✅ Broadcast Channel turns stateless services into networked ones
✅ Simplicity wins — one TypeScript file > 4 services
📚 Resources
- Deno Deploy
- BroadcastChannel API
- Deno WebSocket Docs
If you're still binding socket.io to Express in 2024, you're working too hard. Embrace the edge. 🧠
💌 Found this cool or have questions? Email me or drop a DM on Twitter @edgechad 🤘
💡 If you need this done – we offer fullstack development services! Check it out here
Top comments (0)