Deployment
Running PlayMesh in production — Redis, multi-node, Docker, and environment configuration.
Single-node vs. multi-node
Single-node
- No Redis required
- In-memory state & presence
- No background queues
- Great for development
Multi-node (Redis)
- Horizontal scaling
- Distributed state & presence
- BullMQ queues available
- Required for production at scale
Environment configuration
◆server.ts
import { PlayMesh } from '@playmesh/server';
const mesh = new PlayMesh({
port: Number(process.env.PORT ?? 3000),
redis: process.env.REDIS_URL ?? undefined,
socket: {
cors: {
origin: process.env.CLIENT_ORIGIN ?? '*',
methods: ['GET', 'POST'],
},
},
});
◆.env
PORT=4000
REDIS_URL=redis://localhost:6379
CLIENT_ORIGIN=https://game.example.com
JWT_SECRET=your-secret-here
Docker
Dockerfile
◆Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build
ENV NODE_ENV=production PORT=4000
EXPOSE 4000
CMD ["node", "dist/server.js"]
Docker Compose (with Redis)
◆docker-compose.yml
version: '3.9'
services:
redis:
image: redis:7-alpine
volumes: [redis-data:/data]
server:
build: .
environment:
PORT: 4000
REDIS_URL: redis://redis:6379
CLIENT_ORIGIN: http://localhost:3000
ports: ["4000:4000"]
depends_on: [redis]
volumes:
redis-data:
Kubernetes (multi-node)
Scale horizontally by running multiple pods. Each pod connects to the same Redis. Socket.IO's Redis adapter broadcasts across pods.
◆deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: playmesh-server
spec:
replicas: 3
selector:
matchLabels: { app: playmesh-server }
template:
metadata:
labels: { app: playmesh-server }
spec:
containers:
- name: server
image: your-registry/playmesh-server:latest
ports: [{ containerPort: 4000 }]
env:
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: playmesh-secrets
key: redis-url
ℹWebSocket connections require sticky sessions at the load balancer. Configure your ingress with cookie-based or IP-based session affinity.
Cloud platforms
Fly.io
Native multi-region support. Use Fly Redis. Enable sticky sessions in fly.toml.
Railway
Add a Redis service. Set REDIS_URL from Railway's connection string.
AWS ECS
Use ElastiCache for Redis. Configure ALB with duration-based sticky cookies.
AWS EKS
Same as the Kubernetes setup. Use ElastiCache for Redis.
DigitalOcean
App Platform + Managed Redis. Enable session affinity in app settings.
Heroku
Add Redis Cloud. REDIS_URL is set automatically.
Attaching to an existing HTTP server
import express from 'express';
import { createServer } from 'node:http';
import { PlayMesh } from '@playmesh/server';
const app = express();
const httpServer = createServer(app);
app.get('/health', (_req, res) => res.json({ ok: true }));
app.get('/metrics', (_req, res) => res.json(mesh.metrics()));
const mesh = new PlayMesh({ server: httpServer, port: 4000 });
await mesh.start();
Graceful shutdown
process.on('SIGTERM', async () => {
await mesh.shutdown();
process.exit(0);
});
process.on('SIGINT', async () => {
await mesh.shutdown();
process.exit(0);
});