Learn more
Publishing events
In this section, we'll go through the process of publishing events from your backend to Exoquic. We'll look at the important configuration options and how to use them. We'll be using Node.js, but the process is similar for other languages.
Prerequisites
- An API key. Don't have one?
- A backend server (See our list of supported languages). You should never publish events from your frontend because that will expose your API key.
Required fields
Topic
Topics are the way we group events in Exoquic. They can be anything you want, but it's a good idea to use them to group related events. For example, you might use a topic called payment-processing
to group all events related to payment processing, such as payment-succeeded
or payment-failed
.
Important to note is that the order at which events are published and the order at which the events are consumed won't be the same. The ordering is only guaranteed within a channel. For more information on channels, see the Channels section.
While we currently don't enforce a limit on the number of topics, it is preferred to keep the amount of topics low(a few hundred at most). If you find yourself with a lot of topics, you might want to reconsider how you are grouping your events.
Payload
Payload is the data you want to send to the subscribers. The payload is a string of data. For example, in a chat application, the payload could be the message that a user sends and the user id of the sender.
Empty payload - allowed but with special meaning
The payload can be an empty string only when used in conjunction with the Key property. An event with an empty payload and a non-null key is a tombstone event. If a tombstone event is published, Exoquic will eventually delete all the events with the same key. See Tombstone events section for more information.
Example: sending a notification to all users
import ExoquicPublisher from "@exoquic/pub"
const publisher = new ExoquicPublisher({ apiKey: MY_API_KEY });
publisher.publish({
topic: "global-notifications"
payload: JSON.stringify({
message: "We have 20% off sale on all products on Friday! Be there or be square!",
type: "sale",
importance: "high"
})
});
Optional but important fields
Channel
Channels are like topics, but they are used to group events by a specific property. For example, you might use a channel called user-123
to group all events related to user 123. The main difference between topics and channels is that events in the same channel are ordered. A subscriber will always receive events in the same order within a channel.
Channels are commonly used to target events to a specific user. For example, if you are building a chat application, you might want to target all events related to a specific user by using their user id as the channel. That user can then subscribe to all events in that channel.
Channels are cheap
Channels are cheap compared to topics. You can have as many channels as you want.
Example: sending a notification to a specific user
publisher.publish({
topic: "notifications",
channel: "userid-11521",
payload: JSON.stringify({
title: "New message from Stephen B.",
subtitle: "Hey, wanna grab a coff...",
sentAt: 1716877200000,
fromUserId: 53112
})
});
Key
A key is a unique identification for a single or series of events within a topic/channel. The key has multiple uses:
Compaction: Compaction is a mechanism in Exoquic that reduces the size of the stored event log by deleting all the events with the same key except for the latest produced event. You can turn on/off compaction for a topic in your dashboard. This is useful if you have a topic with a lot of churn, such as a topic with a lot of events that are no longer relevant, as often seen with stateful applications.
Tombstone events: A tombstone event is an event with a key and an empty payload. When such an event is published, the events with the same key are marked for deletion. In at most a few hours, the events will be permanently deleted.
Leaving out the channel
Important to note is that if the channel is not set and the key is set, then the channel will be set to the value of the key.
Example with compaction turned on
In this example, compaction will remove the first event(where the user is 29 years old) published in the following sequence:
publisher.publish({
topic: "users",
channel: "user-917",
key: "user-917-updated",
payload: JSON.stringify({
type: "user-updated",
name: "John Doe",
email: "john.doe@example.com",
age: 29 // <---
})
});
// User 917 is updated again. The event above will be permanently
// deleted from Exoquic and only this event will remain.
publisher.publish({
topic: "users",
channel: "user-917",
key: "user-917-updated",
payload: JSON.stringify({
type: "user-updated",
name: "John Doe",
email: "john.doe@example.com",
age: 30 // <---
})
});
Example with tombstone events
In this example, the first event will be a tombstone event for the created event. The second event will be a tombstone event for the updated event. Observe that we use an empty payload and a defined key to create a tombstone event.
// Exoquic will delete all the events with the key
// 'user-917-created' a few hours after publishing
// this event.
publisher.publish({
topic: "users",
channel: "user-917",
key: "user-917-created",
payload: ""
});
// Exoquic will delete all the events with the key
// 'user-917-updated' a few hours after publishing
// this event.
publisher.publish({
topic: "users",
channel: "user-917",
key: "user-917-updated",
payload: ""
});