π₯ 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)