DEV Community

Alex Spinov
Alex Spinov

Posted on

Ably Has a Free API — Here's How to Build Real-Time Features Without Managing WebSockets

A developer I know built a live chat feature with raw WebSockets. It worked great with 10 users. At 1,000 users, messages started dropping. At 10,000, the server crashed. He switched to Ably — it handles millions of concurrent connections without breaking a sweat.

What Ably Offers for Free

Ably free tier:

  • 6 million messages/month
  • 200 peak connections
  • 200 peak channels
  • Pub/Sub messaging with guaranteed delivery
  • Presence — who's online in a channel
  • Message history and persistence
  • WebSocket, SSE, MQTT, REST protocols
  • 99.999% uptime SLA (even on free tier)

Quick Start

npm install ably
Enter fullscreen mode Exit fullscreen mode
const Ably = require('ably');

// Real-time client
const ably = new Ably.Realtime(process.env.ABLY_API_KEY);
const channel = ably.channels.get('chat');

// Subscribe to messages
channel.subscribe('message', (msg) => {
  console.log(`${msg.data.user}: ${msg.data.text}`);
});

// Publish a message
channel.publish('message', { user: 'Alice', text: 'Hello, world!' });
Enter fullscreen mode Exit fullscreen mode

Live Chat Room

// Server-side: token auth (secure)
const Ably = require('ably');
const rest = new Ably.Rest(process.env.ABLY_API_KEY);

app.get('/api/ably-token', async (req, res) => {
  const tokenRequest = await rest.auth.createTokenRequest({
    clientId: req.user.id,
    capability: { 'chat:*': ['publish', 'subscribe', 'presence'] }
  });
  res.json(tokenRequest);
});

// Client-side
const ably = new Ably.Realtime({ authUrl: '/api/ably-token' });
const chatRoom = ably.channels.get('chat:room-123');

// Send message
function sendMessage(text) {
  chatRoom.publish('message', {
    user: currentUser.name,
    text,
    timestamp: Date.now()
  });
}

// Receive messages
chatRoom.subscribe('message', (msg) => {
  appendToChat(msg.data);
});
Enter fullscreen mode Exit fullscreen mode

Presence (Who's Online)

const channel = ably.channels.get('chat:room-123');

// Enter presence
channel.presence.enter({ name: 'Alice', avatar: 'https://...' });

// Get all present members
const members = await channel.presence.get();
console.log(`${members.length} users online`);

// Track presence changes
channel.presence.subscribe('enter', (member) => {
  console.log(`${member.data.name} joined`);
});

channel.presence.subscribe('leave', (member) => {
  console.log(`${member.data.name} left`);
});
Enter fullscreen mode Exit fullscreen mode

REST API

# Publish a message
curl -X POST 'https://rest.ably.io/channels/my-channel/messages' \
  -u 'YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"name": "greeting", "data": "Hello from REST!"}'

# Get channel history
curl 'https://rest.ably.io/channels/my-channel/messages?limit=10' \
  -u 'YOUR_API_KEY'

# Get presence members
curl 'https://rest.ably.io/channels/my-channel/presence' \
  -u 'YOUR_API_KEY'

# Get channel stats
curl 'https://rest.ably.io/stats?unit=hour&limit=24' \
  -u 'YOUR_API_KEY'
Enter fullscreen mode Exit fullscreen mode

Use Cases

  • Live chat — 1-on-1, group, support chat
  • Live updates — sports scores, stock prices, delivery tracking
  • Collaborative editing — multiplayer cursors, shared whiteboards
  • IoT — device-to-cloud messaging via MQTT
  • Gaming — real-time game state synchronization
  • Notifications — instant push to connected clients

Why Ably Over Raw WebSockets

Ably Raw WebSockets
Guaranteed message delivery Messages can drop
Auto-reconnection Build reconnection logic
Message history Build persistence layer
Scales to millions Scale server infrastructure
Presence built in Build presence system
Global edge network Single server location

Need real-time web data? Check out my web scraping actors on Apify — monitor websites in real-time.

Need a real-time data pipeline? Email me at spinov001@gmail.com.

Top comments (0)