AlphornAlphorn Docs

FAQ

Frequently asked questions about Alphorn - self-hosting requirements, retries, message limits, plans, webhook security, SSO, 2FA, and the HTTP API.

General

What is Alphorn?

Alphorn is an open-source, self-hostable notification routing platform. It receives webhooks from your services and routes messages to any combination of channels - Slack, Discord, Email, SMS, PagerDuty, and more - with filtering, retries, and real-time streaming.

How is Alphorn different from ntfy, Apprise, or Gotify?

These tools focus on sending notifications to a single destination. Alphorn is a routing layer - it takes one incoming webhook and fans it out to multiple channels based on filtering rules. You can route critical alerts to PagerDuty and Email while sending informational messages to Slack only, all from a single webhook URL.

Alphorn also provides a full web dashboard for managing webhooks, channels, and delivery logs - plus multi-tenant projects with role-based access control.

Is Alphorn free?

Alphorn is open source under the AGPL-3.0-or-later license (with a commercial license also available). You can self-host it for free with no feature restrictions.

The hosted version at app.alphorn.dev has a free tier (3,000 messages/month, 3 webhooks, 3 channels) and paid plans for higher volume.

Can I use Alphorn without Docker?

Yes. Docker is the easiest way to get started, but you can also run from source by cloning the repository and running with Node.js and pnpm.

Self-Hosting

What infrastructure does Alphorn need?

Just PostgreSQL. No Redis, no MongoDB, no separate message queue - the delivery queue runs inside PostgreSQL too. By default Alphorn runs as a single process that handles both the web dashboard and notification delivery.

What PostgreSQL version do I need?

PostgreSQL 18 or higher. Alphorn uses the built-in uuidv7() function, which was added in PostgreSQL 18.

How do I update my self-hosted instance?

With the prebuilt Docker image: pull the latest image and restart - migrations run automatically on startup. When running from source, pull the code, then run pnpm install, pnpm db:deploy, and pnpm build. See the Self-Hosting guide for details.

Can I run Alphorn behind a reverse proxy?

Yes - and you should, because Alphorn needs HTTPS for logins (except on localhost). Alphorn runs on port 3000 by default. Put it behind Nginx, Caddy, Traefik, or any reverse proxy, set BETTER_AUTH_URL to the public https:// URL, and pass the client IP in X-Forwarded-For. See Self-Hosting → Reverse Proxy & HTTPS.

Reliability

What happens when a channel is down?

Alphorn makes up to 5 delivery attempts with exponential backoff, starting at about 30 seconds - all attempts are done within roughly 15 minutes. If all attempts fail, the delivery is marked as failed and you can configure failure notifications to alert you via a backup channel. See Retries for details.

Are messages stored?

Notification payloads and delivery logs are stored in PostgreSQL. You can view delivery history, status, and error details in the dashboard.

On the hosted service, messages are kept for 7 days (Free), 30 days (Pro), or 90 days (Business). Self-hosted instances have no automatic retention - messages are kept indefinitely, so plan your database size accordingly.

What counts toward my message limit?

Each accepted webhook request counts as one message, regardless of how many channels it's routed to. Test messages sent from the dashboard count too.

Security

Is my data encrypted?

All communication with the hosted service uses TLS (HTTPS). For self-hosted instances, encryption depends on your infrastructure - use a reverse proxy with TLS for production deployments.

Webhooks can additionally require an API key (switch on Require API key), and Alphorn stores only a hash of each key. Treat API keys and webhook URLs like passwords.

Can someone discover my webhook URLs?

Webhook URLs contain a random, unguessable ID. By default the URL is the only secret. Switch on Require API key on the webhook page and every request must also send Authorization: Bearer <api-key>, so knowing the URL alone isn't enough. Don't share API keys or webhook URLs in public repositories or logs. If one leaks, regenerate it on the webhook page.

Does Alphorn support SSO?

Yes. Alphorn supports GitHub, Google, Microsoft, and any OIDC-compliant identity provider (Keycloak, Okta, Azure AD, etc.). See Authentication for details.

Is two-factor authentication available?

Yes. Alphorn supports TOTP-based 2FA with backup codes. Project owners and admins can require 2FA for all members. See Authentication → Two-Factor Authentication.

Channels

Can I add a channel that isn't listed?

Yes. The Webhook channel type lets you send notifications to any HTTP endpoint. If a service accepts webhooks or has an API, you can connect it.

Can I send to multiple channels at once?

That's the core idea. When a notification arrives, Alphorn evaluates the filter of each channel linked to the webhook and delivers to every channel that matches. No filter means the channel receives everything.

What happens if I hit my channel limit?

On the free plan, you can configure up to 3 channels and 3 webhooks. Pro allows 15 webhooks and unlimited channels, Business is unlimited. When you reach the limit, you can't add more until you upgrade or delete one - deleted channels and webhooks don't count.

When you downgrade, the oldest channels and webhooks within the new limit stay active and the rest are disabled automatically.

API

Do I need an SDK?

No. Alphorn's API is a simple HTTP POST. Any language or tool that can make HTTP requests works - curl, fetch, requests, http.Post, etc. See the API Reference for examples in multiple languages.

Can I send plain text instead of JSON?

Yes. Send a POST request with Content-Type: text/plain and the message body as plain text. Alphorn also accepts Slack-compatible payloads ({"text": "..."}) for easy migration.

What's the rate limit?

The hosted service has monthly message quotas per plan: 3,000 messages/month (Free), 25,000 (Pro), or 500,000 (Business). The API returns HTTP 429 when you exceed your quota. Self-hosted instances without billing configured have no quota.

On this page