DEV Community

Cover image for Building a Notification Center: Architecture, Code, and Platform Comparison
kysy
kysy

Posted on

Building a Notification Center: Architecture, Code, and Platform Comparison

Building a Notification Center: Architecture, Code, and Platform Comparison

Notification centers are a big deal for applications, but go largely unnoticed by users. This is by design.

If you're building one, here's what you need to know about the architecture, technical implementation, and how different platforms compare.

## What is a notification center?

A notification center is an in-app interface that displays a persistent history of messages and updates. The key difference from other notification types: it sticks around. Push notifications appear on your lock screen and vanish. Toast messages pop up for a few seconds and disappear. A notification center maintains a permanent record that users can review whenever they want.

Look at Instagram or LinkedIn. The bell icon shows everything that happened since you last checked. Comments, mentions, activity. That's a notification center doing its job.

The distinction matters because each notification type serves different purposes. Push is interruptive and happens outside your app. Toasts appear briefly inside your app for immediate feedback. The notification center is always available for users to browse on their own timeline.

The three-layer architecture

Building a notification center means coordinating three distinct layers:

Backend layer

Your application triggers notification events when something happens that users need to know about. The notification API receives these events and processes them, determining who should receive the notification, what it should say, and where it should go. Message routing figures out which channels to use based on rules and user preferences. User preferences filter what actually gets sent. This layer handles all the decision-making logic.

Delivery layer

WebSocket connections handle real-time delivery so messages appear instantly without polling. Message persistence ensures nothing gets lost if users are offline when the notification fires. State synchronization keeps everything consistent across devices, so marking something read on your phone marks it read on your laptop. Integration with push notification services handles mobile notifications through APNs and FCM. This layer is pure infrastructure.

Frontend layer

UI components display the inbox, toasts, and badges. State management tracks which messages are read, unread, or archived. User authentication ensures people only see their own notifications. Real-time updates make new messages appear instantly. This is what users see and interact with.

The flow looks like this:

your application fires an event → notification API receives it → message routing checks preferences → WebSocket delivers to open sessions while storing for later → user marks as read → state update syncs everywhere
Enter fullscreen mode Exit fullscreen mode

Every layer has failure modes. WebSockets drop. Databases go down. Users lose connectivity. Mobile apps get suspended. A robust notification center needs retry logic, queuing, fallbacks, and extensive monitoring. This complexity is why many in-house implementations end up feeling unreliable.

Core technical requirements

Real-time WebSocket delivery

Messages should appear instantly without user action. The technical challenge is that WebSocket connections are stateful and break constantly. Users walk into elevators, switch networks, apps get backgrounded. You need automatic reconnection, authentication reestablishment, message syncing for disconnected periods, connection health monitoring with heartbeats, and exponential backoff to avoid hammering servers during failures.

Cross-channel state synchronization

Send a notification via inbox and email simultaneously. User reads the email at their desk. They open your mobile app. The inbox notification should already be marked as read because the system knows they dealt with it via email. This same sync needs to work across SMS, push, and any other channels. The goal is making users experience one notification, not separate copies they dismiss individually on each channel.

Multi-device synchronization

Users switch between web, iOS, and Android constantly. Read on your phone during your commute, it's marked read on your laptop at the office. Archive on your laptop, it vanishes from your phone. This requires maintaining a single source of truth for message state while handling devices that aren't always connected, clocks that aren't synchronized, and users taking actions on multiple devices simultaneously. You need conflict resolution, offline queuing, and efficient sync protocols.

User preference management

Users need control over what they receive and how. Some want every notification. Others want almost none. Most want something specific: mentions and direct messages but not routine updates, approvals via inbox and email but updates only to inbox, no notifications after 8pm except critical alerts. You need preferences per notification type, channel selection per category, quiet hours, and subscription topic management.

Implementation with code examples

Here's what implementation looks like across platforms.

React web application

npm install @trycourier/courier-react
Enter fullscreen mode Exit fullscreen mode
import { CourierProvider } from "@trycourier/courier-react";

function App() {
  return (
    <CourierProvider 
      userId="user_123"
      clientKey={process.env.REACT_APP_COURIER_CLIENT_KEY}
    >
      {/* Your app components */}
    </CourierProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode
import { CourierInbox } from "@trycourier/courier-react";
import { useEffect } from "react";

export default function NotificationCenter() {
  const courier = useCourier();

  useEffect(() => {
    courier.shared.signIn({
      userId: 'user_123',
      jwt: 'your_jwt_token'
    });
  }, []);

  return (
    <div>
      <h1>Notifications</h1>
      <CourierInbox />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Three components and you have real-time delivery, cross-device sync, and all the infrastructure working. The inbox component handles WebSocket connection management, message rendering, state updates, and user interactions.

iOS implementation

import Courier_iOS

// Authenticate
Courier.shared.signIn(
  userId: "user_123",
  jwt: "your_jwt_token"
)

// UIKit
let inbox = CourierInbox()
view.addSubview(inbox)

// Or in SwiftUI
struct ContentView: View {
  var body: some View {
    VStack {
      Text("Notifications")
      CourierInboxView()
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Android implementation

import com.courier.android.Courier

class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    Courier.shared.signIn(
      userId = "user_123",
      jwt = "your_jwt_token"
    )

    setContent {
      CourierInbox()
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Sending notifications

const { requestId } = await courier.send({
  message: {
    to: {
      user_id: "user_123",
      email: "[email protected]",
      phone_number: "+1234567890"
    },
    content: {
      title: "Order Shipped",
      body: "Your order #12345 has shipped and will arrive tomorrow"
    },
    routing: {
      method: "all",
      channels: ["inbox", "email", "push", "sms"]
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

One API call sends to multiple channels. The same content automatically adapts to each channel's format. The inbox message includes rich text and action buttons. The email renders as HTML with responsive design. The push notification condenses to title and body for a lock screen. The SMS becomes plain text with shortened links.

Using templates

const { requestId } = await courier.send({
  message: {
    to: { user_id: "user_123" },
    template: "comment-notification",
    data: {
      commenter: "Sarah",
      post_title: "Q4 Planning",
      comment_preview: "Great insights on the roadmap..."
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

Templates let you reference pre-built notification designs by ID and pass in dynamic data. Non-technical team members can edit template content without touching code.

Platform comparison

Courier

Courier is built for anyone to ship notifications, not just developers. Pre-built UI components work across web and mobile. One API call handles multi-channel orchestration across inbox, email, push, SMS, and chat platforms like Slack, Microsoft Teams, and WhatsApp Business.

Cross-channel state synchronization is automatic. Visual workflow builder lets product managers and marketers create notification logic without code. Hosted preference management means you don't build preference UIs.

Good for B2B SaaS, developer tools, and applications where notifications are a feature but not the core product. Implementation takes days or weeks. Free tier includes 10,000 notifications per month with full features.

Focuses on transactional and product notifications rather than marketing automation. If you need extensive marketing campaign tools with detailed audience segmentation, look elsewhere.

MoEngage

Marketing automation platform focused on campaigns, audience segmentation, and marketing analytics. Strength is complex customer journeys with detailed user segments based on behavioral data and campaign performance tracking.

The notification center exists but it's secondary to marketing channels. The SDK is heavier because it collects user behavior for segmentation. The implementation approach assumes you're primarily using their dashboard rather than writing code.

Works well for mobile-first consumer apps where marketing campaigns drive growth: e-commerce apps with personalized recommendations, gaming apps with retention campaigns, media apps with content discovery.

The challenge for product notifications is that the platform optimizes for marketing goals. You're working with campaign tools when you need developer infrastructure. The notification center isn't designed as the primary interface, it's an add-on to marketing channels.

Novu

Open-source notification infrastructure. You can self-host the entire stack, which matters for strict data residency requirements or complete infrastructure control. The codebase is public so you can inspect how everything works and contribute changes.

Architecture is similar to Courier with multi-channel support, workflow management, and UI components. The template system lets you design notifications visually. The API abstracts provider complexity so you can switch email or SMS providers without changing application code.

The open-source model means no vendor lock-in. The community contributes integrations and improvements. If something doesn't work how you need, you can fix it yourself.

The tradeoff is operational overhead. Self-hosting means you're responsible for infrastructure, scaling, monitoring, security patches, and upgrades. What you save on service fees you spend on DevOps time. Novu offers managed cloud but it's a smaller team with less infrastructure investment than established platforms.

Makes sense for teams who need self-hosting, want to avoid vendor lock-in, or have DevOps capacity to run notification infrastructure themselves. Less appropriate for teams wanting to focus on product rather than operating infrastructure.

OneSignal

Started as a push notification service and remains strongest there. Deep expertise in push with sophisticated delivery optimization, timezone-based sending, and detailed delivery analytics. They handle millions of push notifications daily.

Expanded to include email, SMS, and in-app messaging, but push is the core strength. The dashboard provides extensive segmentation and targeting for push campaigns. Analytics show detailed metrics about delivery, opens, and conversions specific to push.

Works well for mobile apps where push is the primary channel: gaming apps, news apps, social networks that rely on push for engagement. The free tier is generous for push notifications.

The limitation is OneSignal optimizes for push at the expense of other channels. The inbox capability is basic compared to platforms built around it. Cross-channel orchestration is limited because the platform architecture assumes push is primary. If you need sophisticated in-app notifications or complex workflow automation, the tools are less developed.

Key technical elements

In-app notification centers:

  • Courier provides complete solution with customizable UI components, action buttons, filtering, and real-time sync across devices
  • MoEngage includes a notification center but it's secondary to marketing features
  • Novu provides notification center components with full customization through code
  • OneSignal's in-app messaging is basic compared to dedicated inbox solutions

Multi-channel orchestration:

  • Courier handles complex routing with fallbacks, channel preferences, and cross-channel state sync
  • MoEngage routes messages across channels but optimizes for marketing campaigns rather than transactional flows
  • Novu provides multi-channel support with self-managed infrastructure
  • OneSignal focuses primarily on push with other channels as add-ons

Implementation approach:

  • Courier provides modern SDKs with comprehensive documentation and visual workflow builder for non-technical users
  • MoEngage assumes a marketing team operating a dashboard rather than developers writing code
  • Novu provides modern SDKs with comprehensive documentation, open-source codebase
  • OneSignal has good SDK support but focuses on push implementation patterns

Infrastructure:

  • Courier handles WebSocket scaling, message persistence, and cross-device sync automatically
  • MoEngage provides managed infrastructure optimized for marketing use cases
  • Novu can be self-hosted or managed cloud
  • OneSignal provides managed infrastructure focused on push delivery at scale

Build it yourself considerations

Building in-house timeline: three to six months for something that works in the happy path, another six months for edge cases and production readiness, at least a year for feature parity with existing platforms. That assumes nothing goes wrong and the team stays available.

Engineering resources required: frontend engineers for web, iOS, and Android components. Backend engineers for API, routing logic, WebSocket server, database schema. DevOps for infrastructure, scaling, monitoring, incident response. QA for cross-platform testing and edge cases.

Technical requirements often underestimated: real-time WebSocket infrastructure with reconnection handling, message persistence and efficient querying, user authentication and authorization, cross-device state synchronization with conflict resolution, multi-platform SDKs, provider integrations for APNs, FCM, email, SMS, preference management system, analytics and event logging, template management, GDPR compliance tools, security hardening, performance optimization at scale, 24/7 monitoring.

Most platforms offer free tiers that let you build, test, and validate before committing. Start simple: get the basic inbox working, send test notifications manually, verify cross-device sync actually functions. Then add sophisticated features like action buttons, custom views, and workflow automation.

The important thing is matching the solution to your actual requirements. Not every app needs sophisticated multi-channel orchestration. Not every team needs self-hosted infrastructure. Understanding what you actually need saves you from fighting your tools later.

Top comments (0)