Quality of Service (QoS)

Choose the right delivery guarantee for your messages. NoLag supports three QoS levels for different reliability requirements.

QoS Levels

Quality of Service determines how NoLag handles message delivery. Different use cases require different guarantees:

LevelNameGuaranteeUse Case
0At-most-onceFire and forgetTelemetry, status updates
1At-least-onceAcknowledged deliveryNotifications, chat messages
2Exactly-onceTransactionalPayments, critical events

QoS 0: At-most-once

Messages are sent once with no acknowledgment. The fastest option, but messages may be lost if the connection drops.

// Fire and forget - no delivery confirmation
client.emit('sensors/temperature', { temperature: 72.5 }, { qos: 0 })

Best for:

  • Sensor data that updates frequently
  • Live location updates
  • Typing indicators
  • Mouse cursor positions

QoS 1: At-least-once

Messages are acknowledged by the broker. If no acknowledgment is received, the message is resent. Messages may be delivered more than once.

// Acknowledged delivery
client.emit('notifications', { type: 'alert', message: 'You have a new message' }, { qos: 1 })

Best for:

  • Chat messages
  • Notifications
  • Event broadcasts
  • Most real-time applications

QoS 2: Exactly-once

Messages are delivered exactly once using a four-step handshake. The most reliable but slowest option.

// Exactly-once delivery
client.emit('orders/status', { orderId: '12345', status: 'completed', amount: 99.99 }, { qos: 2 })

Best for:

  • Financial transactions
  • Order processing
  • Critical state changes
  • Inventory updates

Choosing the Right QoS

Decision Guide

  • Can you tolerate lost messages? → Use QoS 0
  • Need delivery confirmation? → Use QoS 1
  • Can't tolerate duplicates? → Use QoS 2
  • Not sure? → Start with QoS 1 (recommended default)

Handling Duplicates (QoS 1)

When using QoS 1, implement idempotency to handle potential duplicate messages:

const processedMessages = new Set()

client.on('orders/new', (data, meta) => {
  // Use a unique identifier from your data
  const messageId = data.orderId

  // Skip if already processed
  if (processedMessages.has(messageId)) {
    return
  }

  // Process the message
  processOrder(data)

  // Mark as processed
  processedMessages.add(messageId)

  // Clean up old IDs periodically
  if (processedMessages.size > 10000) {
    const entries = Array.from(processedMessages)
    entries.slice(0, 5000).forEach(id => processedMessages.delete(id))
  }
})

Default QoS

You can set a default QoS level for all messages:

import { NoLag } from '@nolag/js-sdk'

// Set default QoS for all messages
const client = NoLag('your_access_token', {
  qos: 1  // Default QoS level
})

await client.connect()

// Override per-message
client.emit('topic', data, { qos: 2 })

Next Steps