Most apps eventually need to reach users outside the app itself. A background sync completes, a purchase is confirmed, a security alert fires. The question is not whether you need messaging, it is which channel to use and how to wire it up without managing separate services for each one.
Appwrite Messaging handles push notifications, email, and SMS from a single API. You configure providers once, define targets per user, and send or schedule messages to individuals, groups, or topics. This post covers the two highest-traffic channels: push notifications and email.
Why keeping messaging in one place matters
The alternative is common and painful: a push library from Firebase, a transactional email service with its own SDK, an SMS provider on top of that. Each has separate authentication, separate dashboards, and separate retry logic to maintain.
When everything lives in Appwrite Messaging, your targeting logic (which user, which channel, which topic) is written once. You can also schedule messages from the same API, so a single call handles "send now" and "send in 48 hours" identically.
Choosing the right channel
Before writing any code, match the message to the channel.
Push notifications are best for time-sensitive information that the user should see quickly: a new chat message, a delivery update, a security alert. They appear on the lock screen and interrupt whatever the user is doing, so reserve them for content that earns that interruption.
Email is better for content with longer shelf life or more detail: receipts, invoices, newsletters, password resets, weekly digests. Users expect to find email later; they do not expect a push notification from three days ago to still be relevant.
SMS sits between the two. It is high-visibility like push, but more appropriate for one-time passcodes and delivery notifications where the user may not have the app installed.
Setting up push notifications
Push notifications on mobile require a provider. Apple devices use APNs (Apple Push Notification service); Android devices use FCM (Firebase Cloud Messaging). Appwrite supports both.
Start by adding a provider in the Appwrite Console under Messaging > Providers > Add provider > Push notification. Select APNs or FCM and supply your credentials. For APNs, you need an authentication key from your Apple Developer account. For FCM, you need a service account JSON from the Firebase Console.
Once the provider is configured, your app needs to register a push target for each logged-in user. A push target links a device token to an Appwrite account.
For Android with FCM, fetch the registration token after Firebase initializes and create a push target when the user logs in:
val session = account.createEmailPasswordSession(email, password)
val target = account.createPushTarget(
targetId = ID.unique(),
identifier = fcmToken
)
For iOS with APNs, register for remote notifications in your app delegate, capture the device token, and create the push target the same way:
let target = try await account.createPushTarget(
targetId: ID.unique(),
identifier: apnsToken
)
FCM tokens can rotate, so you also need to handle the refresh event and call updatePushTarget with the new token to keep targeting accurate.
Sending a push notification
With a provider and targets set up, you can send from the Console or via the Server SDK. Here is a Node.js example:
const message = await messaging.createPush({
messageId: ID.unique(),
title: 'Your order has shipped',
body: 'Estimated delivery: tomorrow by 5pm.',
users: ['user-id-here'],
});
The users array accepts Appwrite user IDs. You can also pass targets (specific device tokens) or topics (groups of subscribers) depending on how broadly you want to reach.
Setting up email
Email in Appwrite Messaging requires an SMTP provider. Appwrite supports Mailgun and SendGrid. Add one under Messaging > Providers > Add provider > Email, then follow the configuration wizard.
Users who signed up with email and password already have an email target attached to their account. For users who signed up another way, you can add an email target programmatically:
const target = await users.createTarget({
userId,
targetId: ID.unique(),
providerType: sdk.MessagingProviderType.Email,
identifier: 'user@example.com',
providerId
});
Sending an email
const message = await messaging.createEmail({
messageId: ID.unique(),
subject: 'Your invoice from Acme',
content: '<h1>Invoice #1042</h1><p>Due: April 1, 2026</p>',
users: ['user-id-here'],
});
For HTML email, pass the full markup in the content field. If you are sending plain text, leave out HTML tags. Appwrite handles delivery through the configured SMTP provider.
Customer identity without the hassle
Add secure authentication in minutes, not weeks.
Built-in security and compliance
Multiple login methods
Custom authentication flows
Multi-factor authentication
Targeting with topics
For broadcast scenarios, like pushing a feature announcement to all users on a specific plan, topics are the right tool. Create a topic in the Console or via the API, subscribe users or targets to it, then send to the topic ID instead of individual user IDs:
const message = await messaging.createPush({
messageId: ID.unique(),
title: 'New feature: dark mode',
body: 'Dark mode is now available in settings.',
topics: ['pro-plan-users'],
});
Appwrite resolves the topic to all subscribed targets automatically. You do not need to paginate through user lists or build your own fanout logic.
Scheduling messages
Both push and email support scheduled delivery. Add a scheduledAt field with an ISO 8601 timestamp and Appwrite handles the rest:
const message = await messaging.createEmail({
messageId: ID.unique(),
subject: 'Weekly digest',
content: digest,
topics: ['all-users'],
scheduledAt: '2026-04-01T09:00:00+00:00',
});
This is useful for newsletters, reminder sequences, and any situation where you want to queue messages in advance.



