Offline Message Queueing & Delivery π¬
Never lose a message again! Vaultys Peer SDK automatically handles offline peers with intelligent message queueing and guaranteed delivery.
π― The Challenge of P2P Messagingβ
In traditional P2P applications, if a peer is offline, messages are lost. This creates a poor user experience:
- β Users miss important messages
- β Manual retry logic is complex
- β No delivery guarantees
- β Poor reliability perception
β¨ Our Solution: Seamless Offline Handlingβ
Vaultys Peer SDK solves this with automatic message queueing:
- β 100% message delivery - Messages queue when peers are offline
- β Seamless reconnection - Queued messages deliver automatically
- β
No code changes - Works with existing
sendMessage()calls - β Persistent storage - Queues survive app restarts
- β Smart retry logic - Exponential backoff prevents overload
π Zero-Configuration Usageβ
Message queueing works out of the box - no configuration needed!
import { setupVaultysPeerSDK } from '@vaultys/peer-sdk';
const peer = setupVaultysPeerSDK();
await peer.initialize('did:vaultys:alice');
// Just send messages normally - queueing is automatic!
await peer.sendMessage('did:vaultys:bob', 'Hello Bob!');
// If Bob is offline, message queues automatically
// When Bob comes online, message delivers seamlessly
π How It Worksβ
Message Flow Diagramβ
Queue Behaviorβ
- Detection: SDK automatically detects if peer is offline
- Queueing: Messages are queued in order (FIFO)
- Storage: Queue persists to configured storage provider
- Monitoring: SDK monitors for peer reconnection
- Delivery: When peer reconnects, messages deliver in order
- Confirmation: Delivery is confirmed before removing from queue
π¨ Configuration Optionsβ
While queueing works by default, you can customize the behavior:
const peer = setupVaultysPeerSDK({
messageQueue: {
// Enable/disable queueing (default: true)
enabled: true,
// Maximum messages to queue per peer
maxQueueSize: 1000,
// Maximum time to keep messages (ms)
maxQueueTime: 7 * 24 * 60 * 60 * 1000, // 7 days
// Persist queue to storage (survives restarts)
persistQueue: true,
// Retry strategy
retryStrategy: 'exponential', // or 'linear', 'fixed'
// Initial retry delay (ms)
retryDelay: 1000,
// Maximum retry attempts
maxRetries: 10,
// Batch delivery size
batchSize: 50,
// Compress queued messages
compression: true
}
});
π‘ Common Patternsβ
1. Send and Forgetβ
The simplest pattern - just send messages without worrying about online status:
// No need to check if peer is online!
async function sendChatMessage(did: string, text: string) {
await peer.sendMessage(did, text);
// SDK handles everything else
}
2. Track Delivery Statusβ
Monitor when messages are actually delivered:
// Send with tracking
const messageId = await peer.sendMessage(did, 'Important message');
// Track delivery
peer.on('message-delivered', (delivery) => {
if (delivery.messageId === messageId) {
console.log('β
Message delivered at:', delivery.timestamp);
updateUIDeliveryStatus(messageId, 'delivered');
}
});
// Track queueing
peer.on('message-queued', (event) => {
console.log('π¬ Message queued for offline peer:', event.to);
updateUIDeliveryStatus(event.messageId, 'pending');
});
3. Priority Messagesβ
Send high-priority messages that deliver first:
// High priority message
await peer.sendMessage(did, 'URGENT: Server maintenance', 'text', null, {
priority: 'high',
skipQueue: false // Still queue if offline
});
// Normal priority (default)
await peer.sendMessage(did, 'Regular update');
4. Bulk Messagingβ
Send to multiple peers efficiently:
// Send to multiple peers - each queues independently
const recipients = ['did:vaultys:alice', 'did:vaultys:bob', 'did:vaultys:charlie'];
const results = await Promise.all(
recipients.map(did =>
peer.sendMessage(did, 'Team announcement')
.then(id => ({ did, messageId: id, status: 'sent' }))
.catch(err => ({ did, error: err, status: 'failed' }))
)
);
// Some may be delivered immediately, others queued
console.log('Delivery results:', results);
5. Queue Managementβ
Inspect and manage the message queue:
// Get queue status
const queueInfo = peer.getQueueInfo();
console.log(`Total queued messages: ${queueInfo.totalMessages}`);
console.log(`Peers with queued messages: ${queueInfo.peersWithMessages}`);
// Get queued messages for specific peer
const queuedMessages = peer.getQueuedMessages('did:vaultys:bob');
console.log(`${queuedMessages.length} messages queued for Bob`);
// Clear queue for specific peer (use with caution!)
await peer.clearQueue('did:vaultys:bob');
// Retry failed messages immediately
await peer.retryFailedMessages();
π Retry Strategiesβ
Exponential Backoff (Default)β
Delays double with each retry, preventing server overload:
// Retry delays: 1s, 2s, 4s, 8s, 16s, 32s...
const peer = setupVaultysPeerSDK({
messageQueue: {
retryStrategy: 'exponential',
retryDelay: 1000,
maxRetries: 10
}
});
Linear Backoffβ
Delays increase linearly:
// Retry delays: 1s, 2s, 3s, 4s, 5s...
const peer = setupVaultysPeerSDK({
messageQueue: {
retryStrategy: 'linear',
retryDelay: 1000,
maxRetries: 10
}
});
Fixed Intervalβ
Same delay between retries:
// Retry every 5 seconds
const peer = setupVaultysPeerSDK({
messageQueue: {
retryStrategy: 'fixed',
retryDelay: 5000,
maxRetries: 10
}
});
π― Advanced Featuresβ
Message Deduplicationβ
Prevents duplicate messages from being queued:
const peer = setupVaultysPeerSDK({
messageQueue: {
deduplication: true,
deduplicationWindow: 60000 // 1 minute window
}
});
// These will be deduplicated if sent within window
await peer.sendMessage(did, 'Hello');
await peer.sendMessage(did, 'Hello'); // Ignored if within window
Queue Persistenceβ
Queues survive app restarts:
const peer = setupVaultysPeerSDK({
storageProvider: new IndexedDBProvider(), // or any persistent provider
messageQueue: {
persistQueue: true,
persistenceKey: 'vaultys-message-queue'
}
});
// On app restart, queued messages are restored and delivery continues
Batch Deliveryβ
Deliver multiple queued messages efficiently:
const peer = setupVaultysPeerSDK({
messageQueue: {
batchSize: 50, // Deliver up to 50 messages at once
batchDelay: 100 // Wait 100ms between batches
}
});
Message Expirationβ
Auto-remove old messages from queue:
const peer = setupVaultysPeerSDK({
messageQueue: {
maxQueueTime: 24 * 60 * 60 * 1000, // 24 hours
cleanupInterval: 60 * 60 * 1000 // Check every hour
}
});
peer.on('message-expired', (event) => {
console.log('Message expired:', event.messageId);
});
π Coming Soon: Relay Serverβ
We're open-sourcing our production-grade signaling server that also acts as a message relay!
What's Comingβ
// Deploy your own relay server
// docker run -p 9000:9000 vaultys/signaling-relay
const peer = setupVaultysPeerSDK({
relay: {
host: 'your-relay.com',
port: 9000
},
relay: {
enabled: true,
maxOfflineTime: '30d', // Store for 30 days
maxMessageSize: '100MB', // Support large files
encryptAtRest: true, // Server-side encryption
}
});
// Messages relay through server for extended offline periods
await peer.sendMessage(did, 'Delivered even after weeks offline!');
Relay Featuresβ
- π¦ Extended Storage: Keep messages for days or weeks
- π End-to-end Encryption: Server can't read messages
- π Analytics: Message delivery metrics
- π Global Distribution: Deploy relays worldwide
- β‘ High Performance: Handle millions of messages
- π Automatic Failover: Multiple relay support
π Monitoring & Metricsβ
Track queue performance:
// Get queue metrics
const metrics = peer.getQueueMetrics();
console.log('Queue metrics:', {
totalQueued: metrics.totalQueued,
totalDelivered: metrics.totalDelivered,
totalFailed: metrics.totalFailed,
averageQueueTime: metrics.averageQueueTime,
deliveryRate: metrics.deliveryRate
});
// Monitor queue events
peer.on('queue-stats', (stats) => {
updateDashboard({
queueSize: stats.size,
oldestMessage: stats.oldestMessageAge,
deliveryRate: stats.deliveryRate
});
});
π― Best Practicesβ
Do's β β
- Let the SDK handle queueing automatically
- Monitor delivery events for UI updates
- Set reasonable queue size limits
- Use persistent storage for important messages
- Implement message expiration for time-sensitive content
Don'ts ββ
- Don't implement manual retry logic
- Don't check peer status before sending
- Don't store unlimited messages
- Don't disable queueing without good reason
- Don't clear queues without user consent
π§ Troubleshootingβ
Common Issuesβ
| Issue | Solution |
|---|---|
| Messages not queueing | Check messageQueue.enabled is true |
| Queue growing too large | Reduce maxQueueSize or add expiration |
| Messages not delivering | Check peer connection and retry settings |
| Duplicate messages | Enable deduplication |
| Lost messages on restart | Enable persistQueue with persistent storage |
Debug Modeβ
const peer = setupVaultysPeerSDK({
debug: true,
messageQueue: {
debugQueue: true // Extra queue logging
}
});
// Monitor all queue operations
peer.on('queue-operation', (op) => {
console.log('Queue operation:', op);
});
π Conclusionβ
With Vaultys Peer SDK's automatic message queueing, you can build reliable P2P applications that work seamlessly regardless of peer connectivity. Your users will never miss a message, and you'll never have to write complex retry logic again!
Next: Learn about Passkey Authentication for passwordless security