How Socket.IO acknowledgments work for reliable messaging
emit with callback, server ack callback, client ack callback, timeout on ack, error handling in ack, delivery confirmation pattern, at-most-once vs at-least-once semantics
Acknowledgments: Synchronous-Style Confirmations
An acknowledgment is a callback passed as the last argument to emit. The receiver calls it to confirm processing:
// Client: emit with ack callback socket.emit('save:draft', { content }, (response) => { if (response.ok) { console.log('Saved, id:', response.id); } else { console.error('Save failed:', response.error); } }); // Server: receive and acknowledge socket.on('save:draft', async (data, callback) => { try { const doc = await db.drafts.save(data); callback({ ok: true, id: doc.id }); } catch (err) { callback({ ok: false, error: err.message }); } });
Ack Timeouts
Acks with no timeout hang forever if the server crashes mid-handler. Use Socket.IO v4's built-in timeout:
socket .timeout(5000) .emit('save:draft', { content }, (err, response) => { if (err) { // Timed out — server did not acknowledge within 5s retryOrNotifyUser(); } else { handleResponse(response); } });
Acknowledgments give you at-most-once delivery confirmation — the server received and processed the message. For guaranteed at-least-once delivery you still need server-side persistence and client-side retry on timeout.
