๐ฅ 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)