In-app notifications without a notification platform
Updated 26 September 2026 · first published 18 September 2026 · by Nordva, who make Nordva Launch
Do I need Knock or Novu for in-app notifications in a small SaaS, or is polling enough?
For a bell icon with a few notification types, a small table plus a polled unread endpoint is enough. A notification platform earns its place when you send over several channels (email, SMS, push), need preferences, digests or batching, or send at a volume where polling costs more than a socket. Knock, Novu and Courier have free tiers; Nordva Launch's are in-app only, polled, and on every plan.
The facts, side by side
Read from each vendor's own pricing page on 24 September 2026. Prices change; follow the links.
| Tool | Free plan | First paid plan | API | MCP server |
|---|---|---|---|---|
| Knock | Yes | $250/month (Starter: 50K messages then $.005 per message, 2.5K guide active users then $.05 per user, 2,000 AI agent credits then $.01 per credit; adds branding removal and email client previews.) | Yes | Yes |
| Novu | Yes | from $30/month (Pro: 30,000+ workflow runs/month then $1.20 per 1K, 7-day activity feed retention, remove Novu branding, advanced email editor, higher rate limits.) | Yes | Yes |
| Courier | Yes | $0.005 per send (pay as you go after 10,000 free sends a month; no fixed monthly figure shown) (Business (the comparison table calls it Pro): unlimited sends, AI translations, AI Agent node, cross-device email testing, email and chat support, 30-day log retention) | Yes | Yes |
| Nordva Launch | Yes: 2 projects, each with 100 waitlist signups and 25 changelog entries; web analytics up to 10,000 events a month and a Stripe connection; API and MCP included; no card | $19/month (Indie), about 20% off annually | Yes: REST, keys scoped to one project (1 to 3 per project by plan), idempotent writes | Yes: mcp.nordva.dev, one server for every primitive, on every plan including Free. Works with Claude Code, Claude Desktop, Cursor, VS Code and Windsurf |
Most “we need notifications” conversations in a small SaaS are about one thing: a bell icon that shows your export is ready, someone commented, your trial ends Friday. That is a table and a polled endpoint. The platforms exist for a different problem, and it is worth knowing which one you have before paying for the other.
What the bell actually needs
- A row per notification: user id, title, body, a link, created and read timestamps.
- A way to create one from your server when something happens.
- An endpoint the client can call to get the unread ones, with a key that is safe in a browser, and a check that the browser is asking about its own user.
- A way to mark one as read.
- Pruning, so the table does not grow forever.
That is the whole product. Polling every 30 to 60 seconds is fine: a tab makes one small request a minute, the endpoint returns a short list, and the badge updates. Nobody notices a 30-second delay on your export is ready.
When that stops being enough
Three things move you to a platform.
Channels. The moment the same event should also go out by email, SMS or push, you need templates per channel, delivery tracking, bounce handling and a place to see what went out. That is what Knock, Novu and Courier are.
Preferences and digests. “Email me daily, not per event”, quiet hours, per-category opt-outs, batching ten comments into one message. Building this well is weeks of work; the platforms have it on the free tier.
Volume. With tens of thousands of concurrently active users, polling becomes a cost line and a socket-based feed is cheaper. All three platforms ship an in-app feed component that handles this.
The three platforms, briefly
Knock is notification infrastructure with the deepest workflow tooling: batching, digests, preference center, send windows, version control for workflows, and an in-app feed. The free Developer plan covers 10,000 messages a month; the first paid plan is $250 a month. There is a CLI and an MCP server.
Novu is open source and can be self-hosted or managed. Workflows across in-app, email, SMS, push and chat, an <Inbox /> component, digests, preferences, quiet hours. The free plan has 10,000 workflow runs a month; Pro starts at $30. An MCP server with 23 tools.
Courier is a notification API with a visual template editor and multi-step journeys across email, SMS, push, Slack, Teams and an in-app inbox, priced per send after a free 10,000 sends a month. It has a hosted MCP server and a CLI.
The polling version, in full
If your situation is the bell and nothing more, here is all of it. The server side is one insert; the client side is one interval.
// server: after the export finishes
await db.insert(notifications).values({ userId, title: "Your export is ready", url: "/exports/42" });
// server: GET /api/notifications/unread → the signed-in user's last 20 unread rows
// (take the user from the session, never from the query string)
// server: PATCH /api/notifications/:id/read
// client
async function poll() {
const r = await fetch("/api/notifications/unread");
render(await r.json());
}
poll();
setInterval(poll, 30_000);
Add a daily job that deletes rows older than 90 days and you are done.
Where Launch fits
Nordva Launch’s notifications primitive is that polling version, hosted, so you do not write the table or the endpoints:
POST /v1/notificationssends to a user id you choose, or to everyone withaudience: "all"; there is no user directory to sync.GET /v1/notifications/inboxis called from the browser with a publishable key and answers with the user’s recent notifications, the unread count andpoll_interval_seconds.- The browser proves which user it is with
user_hash, an HMAC-SHA256 of the user id that your server computes with a signing secret the browser never sees. Without it, anyone with the page’s key could ask for another user’s notifications. PATCH /v1/notifications/{id}/readmarks one read for that user. A broadcast is read separately by each person. Rows are pruned after 90 days.- A changelog entry can post itself to the bell when it publishes.
- Sending accepts an
Idempotency-Key, so a retried job never sends twice. - The MCP tools
send_notification,get_unread_notificationsandmark_notifications_readlet an agent do the same.
It is on every plan (1,000 notifications a month per project on Free, 20,000 on Indie, 200,000 on Builder), next to the changelog, waitlist, feedback and revenue primitives on the same key. It has no channels other than in-app, no preferences, no digests and no socket feed.
Who should not use Launch for this
If you send by email, SMS or push, or need preferences and digests, use Knock, Novu or Courier; all three start free and Launch cannot do those things. If you already run one of them, their in-app feed is included and there is no reason to add a second in-app system.
Questions
- Is polling every 30 seconds bad practice?
- Not at a small product's scale. A user with a tab open makes 120 tiny requests an hour; a thousand active users make 120,000, which a CDN-fronted endpoint answers cheaply. WebSockets or server-sent events start to pay off when you need sub-second delivery or your user count makes the polling volume itself a cost.
- What is the difference between Knock, Novu and Courier?
- All three are multi-channel notification infrastructure: workflows that send email, SMS, push, chat and in-app messages, with user preferences and digests. Novu is open source and can be self-hosted. Courier prices per send. Knock has the deepest workflow tooling and a $250 first paid plan. All three list an MCP server. See the facts table for the checked figures.
- Does Nordva Launch do email or push notifications?
- No. Its notifications primitive is in-app only: send to a user id or to everyone, poll unread, mark read. Email exists elsewhere in Launch for waitlist confirmations, invites, announcements and changelog subscribers, but not as a notification channel.
Try it in your project
npx nordva@latest init
Free plan, no card, no invite.