Backend for solo devs · Invite-only beta

The backend plumbing, pre-built. So your side project gets to the interesting part faster.

Paean is a shared backend I'm building for solo devs juggling more side projects than they have time for. Support inbox, feedback, feature flags, waitlists, cron, files, webhooks — one typed SDK, one API key.

Running on my own projects first. Inviting the waitlist once it's ready for strangers.

Services
9
SDK
TypeScript
Runtime
CF Workers
// How it will look on day one of your side project
import { createPaeanClient } from "@paean/sdk";

const paean = createPaeanClient({
  baseUrl: "https://api.paean.dev",
  apiKey: env.PAEAN_API_KEY,
});

await paean.support.threads.create({
  body: "Can't log in",
  category: "bug",
  reporter_email: "alice@acme.com",
  reporter_name: "Alice",
});
// → { id: "thr_01k…", ref: "PAE-42", created_at: "…" }

↑ The whole integration. Everything else is a Paean concern.

The same nine things. Again.

You've built this backend five times.

Every side project starts the same way. You're excited about the idea, and then you spend the first week wiring the nine services every SaaS needs. By the time the plumbing is done, the spark is gone.

  • Support inbox
  • Waitlist with invite flow
  • Feedback + NPS capture
  • Feature flags with rollout %
  • Cron jobs
  • File uploads to object storage
  • Signed outbound webhooks
  • Email / Discord / HTTP notifiers
  • Public changelog feed

Paean is all nine. Written once, running on Cloudflare's edge, exposed through a typed SDK that runs anywhere JavaScript runs — Workers, Node, Bun, Deno, or an Astro / Next / Hono server endpoint.

What's inside

Nine services. One SDK.

Each has its own admin UI and SDK module. The goal is that using one doesn't force you to adopt all nine — cherry-pick the two that solve your immediate pain and wire up the rest when you need them.

01

Support inbox

Threads with categories, custom statuses, tags, agent replies, public reporter lookup, and an inbound-email reply path. Per-tenant scoping, soft-delete, seeded from your contact form, the SDK, the `<paean-support-form>` web component, or MCP.

02

Feedback & NPS

1–10 ratings with optional comment. Stats endpoint per project. Auto-capture hook designed for MCP-driven apps.

03

Feature Flags

On/off flags with stable rollout percentage. KV hot-path cache. Missing-config path returns disabled rather than guessing.

04

Waitlist

Capture → invite flow with email. Status transitions (pending → invited → joined). Referrer tag if you want to track source.

05

Cron

Per-tenant scheduled jobs. Minute-tick scheduler. Separates transient vs permanent failures so retries stop when they should.

06

Files

R2-backed uploads, streaming in and out. 10MB cap, allow-listed content types, SVG XSS scrub on the way in.

07

Webhooks

Inbound relay with HMAC verification. Outbound signing in the Stripe-style `t=<unix>,v1=<hex>` format. Retry table for failed deliveries.

08

Notifiers

Rule-based email, Discord, and generic HTTP. SSRF-guarded outbound with IPv4 normalisation. Template substitution per event.

09

Changelog

Public JSON feed with a 60-second KV cache. Admin CRUD. Fires a `changelog.published` event when an entry flips from draft.

The diff

Two hundred lines. Now four.

A support-thread ingestion endpoint you've written before — auth, validation, D1 writes, email fan-out, the error envelope you'll regret.

Before — hand-rolled Hono route
import { Hono } from "hono";
import { z } from "zod";
import { drizzle } from "drizzle-orm/d1";
import { Resend } from "resend";
// + api-key auth middleware
// + rate-limit middleware
// + D1 schema migrations
// + cross-tenant isolation
// + soft-delete cascade
// + IP hashing for privacy
// + request_logs table
// + error envelope
// + Sentry capture
// + outbound webhook signing
// + tests for all of the above

app.post("/support/threads", auth, tenant, rateLimit, async (c) => {
  /* … 180 more lines … */
});
After — Paean SDK
import { createPaeanClient } from "@paean/sdk";

const paean = createPaeanClient({
  baseUrl: "https://api.paean.dev",
  apiKey: env.PAEAN_API_KEY,
});

await paean.support.threads.create({ body, category, reporter_email, reporter_name });

// Included for free:
//   ✓ scoped API key auth
//   ✓ per-tenant rate limit
//   ✓ cross-tenant isolation
//   ✓ IP-subnet-hashed request log
//   ✓ retry on transient 5xx (GET)
//   ✓ X-Paean-Request-Id correlation
//   ✓ notifier fan-out (email/Discord/HTTP)
//   ✓ admin SPA to manage it all

Pricing · Planned

How it'll be priced, when it opens.

Nothing is taking cards yet. The shape below is what I'm planning — subject to change based on what usage actually looks like once there's real traffic. If you want in early, the waitlist is the way.

Hobby

For your first side project.

$0 / forever
  • 1 project
  • 1,000 ops / month
  • All 9 services
  • TypeScript SDK + REST
  • Community support
Coming soon

Get invited →

Most popular (planned)

Indie

For the portfolio dev.

$19 / per month
  • 5 projects
  • 50,000 ops / month
  • Email delivery via Resend
  • Signed outbound webhooks
  • Priority email support (48h)
Coming soon

Get invited →

Maker

When a side project becomes a business.

$49 / per month
  • Unlimited projects
  • 250,000 ops / month
  • 3 team seats
  • Priority email support (12h)
  • Audit-log export
Coming soon

Get invited →

An op is any billable API call — a support thread create, flag eval, cron fire, webhook delivery. Exact rules settle once I've watched a few weeks of real traffic.

Early access

Leave an email. I'll invite you when it's ready.

Paean is running — I use it for my own projects — but it isn't open to strangers yet. I want to stress-test it on real traffic with people I can actually respond to before flipping the signup switch. Leave your email and I'll invite you when the next slot opens.

Uses Paean's own waitlist service. No marketing emails — just the invite when it's your turn.

Questions

Things people ask me.

How ready is this, really?

I've built it, deployed it, and run it for my own projects. I haven't put it through a stress test with real user traffic yet — that's what the waitlist is for. When the first handful of invited users are in and the sharp edges are sanded down, the gates open to strangers. Until then: building in public, not selling.

How is this different from Supabase, Firebase, or Pocketbase?

Those are general-purpose BaaS — database + auth, and you build features on top. Paean is opinionated feature-layer BaaS: support inbox, feedback, flags, waitlists, cron, files, webhooks, notifiers. The stuff every indie SaaS rebuilds. You'd use Paean for the repeat plumbing and your favourite DB for your own domain logic.

Do I need to be on Cloudflare to use it?

No. Paean runs on Cloudflare; your app can live anywhere. If you're on CF Workers the SDK will use a service binding (zero egress). Otherwise it's HTTPS from Node, Bun, Deno, Astro, Next, Hono, or a plain fetch.

What does the free tier actually look like?

Planned: 1 project, 1,000 ops a month, all nine services. Enough for a landing page waitlist, a side project's support inbox, or a feature-flag experiment. Numbers can still shift before launch based on what real usage costs me.

What about GDPR, data residency, deletion?

Data will live in Cloudflare D1 and R2. Soft-delete is first-class across every model — rows are marked and excluded from reads immediately. Hard-delete and full data-export endpoints are on the roadmap; if you need either before I ship them, the waitlist form asks about use cases and I'll prioritise.

Can I use it from Python or Go?

Not with a first-class SDK yet — TypeScript is the only typed client. Every endpoint has a stable REST surface with JSON envelopes, so any HTTP client works. Python and Go SDKs ship when there's enough signal from real users that it's worth maintaining them properly.

Who's building this?

A solo dev from Melbourne. I run it while running my own SaaS projects, which means: I use it before you do, I reply to bug reports personally, and I won't pivot it to enterprise. What I can't promise is a big team's response time — if you file a non-critical bug on a Saturday, it's Monday.

What happens if this project gets abandoned?

Your data sits in Cloudflare D1 + R2 — structured, exportable. If Paean winds down I commit to 90 days written notice, the final billing cycle refunded, and an export script targeting your own CF account. It's in the terms of service.

Before you go

Leave an email so you hear when it's ready.

The waitlist is the only way in right now. Paid tiers light up after the first group of invited users has run real workloads through it without anything falling over.