Notifications Architecture for SaaS at Pre-Seed Stage
Notifications are how your product communicates with users outside of active sessions. At pre-seed, most teams underinvest in notifications — they send a welcome email and nothing else — and then wonder why activation and retention are low. Notifications done well drive users back into the product at the right moment. Notifications done poorly train users to ignore or unsubscribe from everything you send.
This guide covers the architecture decisions pre-seed teams need to make: which channels to support, how to separate transactional from product notifications, and how to build user preference controls without overengineering.
📡 Notification Types and Channel Selection
| Notification Type | Channel | Pre-Seed Priority | Example |
|---|---|---|---|
| Transactional | Required | Welcome email, password reset, billing receipts | |
| Product / activity | Email or in-app | High | "Your report is ready", "Someone commented on your doc" |
| Onboarding drip | High | Day 1, Day 3, Day 7 activation nudges | |
| Digest / summary | Medium | Weekly usage summary, team activity digest | |
| In-app alerts | In-app banner or toast | Medium | New feature announcement, account limit warning |
| Push notifications | Browser push or mobile push | Low (add later) | Real-time alerts for time-sensitive events |
At pre-seed, build email and in-app. Skip push notifications until you have evidence that email alone is insufficient to re-engage your users — which is rare at early stage.
📧 Transactional Email Stack
Transactional emails (welcome, password reset, billing confirmation, account alerts) must be reliable, templated, and delivered immediately. They are not marketing emails — they are product functionality delivered via email.
Pre-seed transactional email stack:
- → Provider: Resend, Postmark, or SendGrid. Resend has the best developer experience for modern Node.js / Next.js stacks. Postmark has the best deliverability reputation for transactional mail. Both have free tiers sufficient for pre-seed volume.
- → Templates: Use React Email or MJML to write HTML email templates in code. Store templates in your repository — not in the email provider's GUI. This makes templates reviewable, versionable, and testable.
- → Sending pattern: Call the email API directly from your backend for transactional emails. Do not queue transactional emails — they need to send immediately. Queue marketing and product emails to avoid blocking your main request cycle.
// Resend transactional email example
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'no-reply@yourproduct.com',
to: user.email,
subject: 'Welcome to YourProduct',
react: WelcomeEmail({ name: user.name }),
});
🔔 In-App Notifications
In-app notifications appear inside the product: a notification bell with a dropdown, a toast/snackbar for immediate feedback, or a banner for account-level alerts. At pre-seed, you need two patterns: toasts for immediate feedback and a notification feed for persistent alerts.
Toast notifications: Used for action confirmations ("Report saved", "Member invited") and error alerts. Render client-side, dismissed automatically after 3–5 seconds. No database storage required — state lives in the component.
Notification feed (bell icon): Used for asynchronous product events ("Someone commented on your document", "Your export is ready"). Requires database storage:
CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
type TEXT NOT NULL, -- 'comment', 'export_ready', 'mention'
payload JSONB, -- event-specific data
read_at TIMESTAMPTZ, -- null = unread
created_at TIMESTAMPTZ DEFAULT NOW()
);Poll this table on page load and mark notifications read when the user opens the feed. Real-time delivery (WebSocket or SSE) is a nice-to-have — add it when user complaints about delayed notifications appear, not before.
⚙️ User Notification Preferences
Build notification preferences before users ask for them. The absence of preferences drives unsubscribes — users who cannot control what they receive will opt out of everything.
Pre-seed minimum preference model:
- → Transactional emails: Always on, no preference toggle. Users cannot opt out of password resets or billing receipts.
- → Product activity emails: On by default, user can disable. Covers activity notifications sent via email.
- → Marketing and drip emails: On by default, user can disable. Must honor unsubscribes within 10 days (CAN-SPAM) — use your email provider's list-unsubscribe support.
- → In-app notifications: On by default; no preference needed at pre-seed. Users can dismiss individual notifications.
Store preferences on the user record as a JSON column:
ALTER TABLE users ADD COLUMN notification_preferences JSONB DEFAULT
'{"product_emails": true, "marketing_emails": true}'::jsonb;
What to Do Next
If you have no notification system: start with the transactional email stack — welcome email, password reset, billing receipt — using Resend or Postmark. These are product requirements, not marketing. Once transactional is working, add an onboarding drip sequence (Day 1, Day 3, Day 7) designed to drive users to their activation milestone. If you have email but no in-app notifications: add the notifications table and a bell icon with unread count. Users who receive a notification in-app are significantly more likely to return to the product than users who receive only email.