Buzzbuzz

Overview

Buzzbuzz is responsible for creating and storing notification records and UserNotificationPreferences as well as for sending notifications (push and email). Buzzbuzz is the only service that sends emails or interacts with the underlying push notification APIs.

Buzzbuzz is also responsible for Reminders, as these trigger notifications and are themselves effectively a notification.

Unlike most of the Pivot backend services which are written in Go, Buzzbuzz is written in TypeScript as a Node.js server. This enables Buzzbuzz to use jsx-email for writing HTML emails and to use the Expo expo-server-sdk for interacting with the Expo Push Notifications Service.

API

Buzzbuzz supports sync gRPC requests to get notifications for a given userId, create/update NotficationPreferences, save push notification tokens, create/update UserReminders, as well as to send emails like 'magic link' on behalf of the Visa service to support the email-based sign in/up flows.

Buzzbuzz also supports a generic gRPC method for creating a notification for a user. This is useful for notifications that must be created in the view of another service, where the logic for creating the notification is fundamentally in that other service, e.g. Wallstreet.

Other than the above, communication with Buzzbuzz is async, in the form of Buzzbuzz's consumption of NATS subjects for events that we might want to create notification(s) about. For example, Messenger notifies Buzzbuzz when a new message has been sent in a room, and Facebox notifies Buzzbuzz when a new invite has been created.

It is up to Buzzbuzz to determine:

  1. Whether notification record(s) will be created and for which user(s).
  2. Whether/how to send email/push notifications.

See Notification Logic for detailed flows.

Email Feedback Consumption

Buzzbuzz uses SQS to consume SES feedback and handle/log it.

NATS

Publication

  1. buzzbuzz.change_feed.> whenever an antity is created/updated/deleted. The change feed is scoped to a user, for example buzzbuzz.change_feed.notification.{userId}.createdV1.

Consumption

  1. Subjects that other services write to when events happen that could trigger a notification. For example, messenger.change_feed.message.*.sentV1 and facebox.change_feed.invite.createdV1.

Databases

Buzzbuzz uses Amazon Keyspaces (managed Cassandra) to store the actual notifications it creates, user preferences, and any other metadata about notifications.

  1. Notification – A notification is created for a specific user and is only readable by that user.

  2. NotificationPreference – a user can define various preferences. Root-level, room-level, etc. This complex and dynamic state is tracked with preferences for each user.

  3. Reminder – A user can ask to be reminded about some data in some other service. These are managed through a table.

  4. PushToken – Each user can have multiple Expo push tokens corresponding to app installs on iOS or Android. Buzzbuzz stores those and then uses them to send push notifications.

Temporal Workflows

  1. Notification generation itself is completed via a workflow. Interactions with third-party services are done via activities (Expo Push Notification Service and AWS SES). The workflow also includes checking for an Expo push receipt when sending a push notification

  2. When a notification is snoozed, a workflow starts to unsnooze it. If it is later unsnoozed manually, that workflow is cancelled. The snoozed_until value is used to snooze the workflow.

  3. Reminders are created and sent via a workflow. Each reminder's remind_at time is used to snooze the workflow.

  4. Daily summaries are sent via a scheduled workflow. Whenever a user is created, assuming that user is not an integration, Buzzbuzz creates an enabled UserNotificationPreference for the daily summary and then starts a workflow which sleeps until 2 am local time. When the workflow wakes up, it sends the daily summary, checks Facebox to see if the timezone has changed, and then sleeps again. If the preference is disabled, the workflow is cancelled. If the preference is enabled again, the workflow is re-created.

Deployment

Observability

Security