DEV Community

Cover image for ๐Ÿ”ฅ From Zero to Serverless: Building a Real-Time Chat App with Deno, WebSockets, and No Backend
Yevhen Kozachenko ๐Ÿ‡บ๐Ÿ‡ฆ
Yevhen Kozachenko ๐Ÿ‡บ๐Ÿ‡ฆ

Posted on • Originally published at ekwoster.dev

๐Ÿ”ฅ From Zero to Serverless: Building a Real-Time Chat App with Deno, WebSockets, and No Backend

๐Ÿ”ฅ 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

chat-demo


๐Ÿ“ฆ Getting Started

1. Project Structure

chat-app/
โ”œโ”€โ”€ main.ts # Deno serverless handler
โ””โ”€โ”€ static/
    โ””โ”€โ”€ index.html # UI
Enter fullscreen mode Exit fullscreen mode

๐Ÿง  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;
});
Enter fullscreen mode Exit fullscreen mode

Deploy it Now

You can instantly deploy this with:

deno deploy --project=chat-app main.ts
Enter fullscreen mode Exit fullscreen mode

๐Ÿ’ป 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>
Enter fullscreen mode Exit fullscreen mode

๐Ÿงช 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)