The Complete API Stack for a Modern Web App in 2026
The Complete API Stack for a Modern Web App in 2026
A modern web app touches 10-15 external APIs. Auth, payments, email, storage, search, analytics, monitoring, AI — each is a build-vs-buy decision. Here's the complete API stack with the best provider for each layer, why they win, and what they cost.
The Full Stack Map
┌──────────────────────────────────────────────────┐
│ FRONTEND │
│ Next.js / Remix / SvelteKit / Nuxt │
├──────────────────────────────────────────────────┤
│ │
│ ┌─ IDENTITY ──────────┐ ┌─ PAYMENTS ──────────┐ │
│ │ Clerk / Auth.js │ │ Stripe │ │
│ │ (auth, users, SSO) │ │ (cards, subs, tax) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─ EMAIL ─────────────┐ ┌─ STORAGE ───────────┐ │
│ │ Resend │ │ Cloudflare R2 │ │
│ │ (transactional) │ │ (files, images) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─ DATABASE ──────────┐ ┌─ SEARCH ────────────┐ │
│ │ Neon / PlanetScale │ │ Typesense / Algolia│ │
│ │ (Postgres / MySQL) │ │ (full-text, facets)│ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─ ANALYTICS ─────────┐ ┌─ MONITORING ────────┐ │
│ │ PostHog │ │ Sentry / BetterStack│
│ │ (events, flags) │ │ (errors, logs) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─ AI ────────────────┐ ┌─ COMMUNICATION ─────┐ │
│ │ Anthropic / OpenAI │ │ Twilio (SMS) │ │
│ │ (LLM, embeddings) │ │ Slack (webhooks) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─ DEPLOYMENT ────────┐ ┌─ BACKGROUND JOBS ───┐ │
│ │ Vercel / Fly.io │ │ Inngest / Trigger │ │
│ │ (hosting, CDN) │ │ (queues, cron) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└──────────────────────────────────────────────────┘
Layer by Layer
1. Authentication & Identity
| Provider | Best For | Free Tier | Paid |
|---|---|---|---|
| Clerk | Full-featured, fast setup | 10K MAU | $25/mo (10K+) |
| Auth.js | Self-hosted, open source | Free (OSS) | Hosting costs |
| Supabase Auth | Already using Supabase | 50K MAU | Included |
| WorkOS | Enterprise SSO/SCIM | 1M users | $49/mo |
Winner: Clerk for most apps. Drop-in components, webhooks, org management, and it handles the hardest auth edge cases.
// 3 lines to protect a route
import { auth } from '@clerk/nextjs/server';
export async function GET() {
const { userId } = await auth();
if (!userId) return new Response('Unauthorized', { status: 401 });
// ... your code
}
When to pick something else:
- Self-hosted / open source required → Auth.js
- Already on Supabase → Supabase Auth
- Enterprise SSO is primary requirement → WorkOS
2. Payments & Billing
| Provider | Best For | Transaction Fee | Monthly Fee |
|---|---|---|---|
| Stripe | Everything | 2.9% + $0.30 | None |
| Lemon Squeezy | Digital products, MoR | 5% + $0.50 | None |
| Paddle | SaaS, MoR | 5% + $0.50 | None |
| PayPal | Buyer trust, global | 2.99% + $0.49 | None |
Winner: Stripe for everything except when you need a Merchant of Record (MoR) to handle global tax compliance — then Lemon Squeezy or Paddle.
// Stripe Checkout — 5 lines to accept payment
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: 'price_pro_monthly', quantity: 1 }],
success_url: `${APP_URL}/success`,
cancel_url: `${APP_URL}/pricing`,
});
When to pick something else:
- Don't want to handle taxes/VAT → Lemon Squeezy (Merchant of Record)
- International customers, tax complexity → Paddle
- One-time digital sales → Gumroad or Lemon Squeezy
3. Transactional Email
| Provider | Best For | Free Tier | Cost Per Email |
|---|---|---|---|
| Resend | Developer experience | 3K/month | $0.001 |
| SendGrid | High volume | 100/day | $0.001-0.003 |
| Postmark | Deliverability | 100/month | $0.001 |
| AWS SES | Cheapest at scale | 62K/month (EC2) | $0.0001 |
Winner: Resend for DX — React Email templates, clean API, simple pricing. SendGrid or SES if you're sending millions.
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'App <hello@yourapp.com>',
to: user.email,
subject: 'Welcome!',
react: WelcomeEmail({ name: user.name }),
});
4. File Storage
| Provider | Best For | Free Tier | Cost |
|---|---|---|---|
| Cloudflare R2 | S3-compatible, no egress | 10 GB | $0.015/GB stored |
| AWS S3 | Enterprise, ecosystem | 5 GB | $0.023/GB + egress |
| Vercel Blob | Simple, Vercel-native | 250 MB | $0.023/GB |
| UploadThing | File uploads (React) | 2 GB | $10/mo (100 GB) |
| Supabase Storage | Already using Supabase | 1 GB | Included |
Winner: Cloudflare R2 for most apps — S3-compatible API, zero egress fees, generous free tier.
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
// R2 uses the S3 SDK
const r2 = new S3Client({
region: 'auto',
endpoint: process.env.R2_ENDPOINT,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY!,
secretAccessKey: process.env.R2_SECRET_KEY!,
},
});
await r2.send(new PutObjectCommand({
Bucket: 'my-app',
Key: `uploads/${userId}/${filename}`,
Body: fileBuffer,
ContentType: mimeType,
}));
5. Database
| Provider | Type | Free Tier | Best For |
|---|---|---|---|
| Neon | Serverless Postgres | 0.5 GB | Serverless apps, branching |
| Supabase | Postgres + extras | 500 MB | Full BaaS, real-time |
| PlanetScale | Serverless MySQL | 5 GB | MySQL, schema branching |
| Turso | Edge SQLite (libSQL) | 9 GB | Edge, embedded, low latency |
| Upstash | Serverless Redis | 10K commands/day | Caching, rate limiting |
Winner: Neon for Postgres (serverless scaling, branching, generous free tier). Add Upstash Redis for caching.
// Neon + Drizzle ORM
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
const db = drizzle(sql);
const users = await db.select().from(usersTable).where(eq(usersTable.plan, 'pro'));
6. Search
| Provider | Best For | Free Tier | Cost |
|---|---|---|---|
| Typesense | Self-hosted or cloud | Free (OSS) | $30/mo cloud |
| Algolia | Fastest, richest features | 10K searches/mo | $1/1K searches |
| Meilisearch | Self-hosted, simple | Free (OSS) | Cloud pricing |
| pgvector + Postgres | Already using Postgres | Free | No extra cost |
Winner: Typesense for most apps — open source, typo-tolerant, fast. Algolia if budget isn't a concern and you want the best search UX out of the box.
import Typesense from 'typesense';
const client = new Typesense.Client({
nodes: [{ host: 'search.yourapp.com', port: 443, protocol: 'https' }],
apiKey: process.env.TYPESENSE_API_KEY!,
});
const results = await client.collections('products').documents().search({
q: 'wireless headphones',
query_by: 'name,description',
filter_by: 'price:<100 && in_stock:true',
sort_by: 'popularity:desc',
});
7. Analytics & Feature Flags
| Provider | Best For | Free Tier | Cost |
|---|---|---|---|
| PostHog | All-in-one, open source | 1M events | $0.00031/event |
| Mixpanel | Event analytics | 20M events | $28/mo |
| Plausible | Privacy-first web analytics | None | $9/mo |
| LaunchDarkly | Feature flags (enterprise) | None | $10/seat/mo |
Winner: PostHog — analytics, feature flags, session replay, A/B testing, surveys in one tool. Open source. Generous free tier.
import { PostHog } from 'posthog-node';
const posthog = new PostHog(process.env.POSTHOG_API_KEY!);
// Track events
posthog.capture({ distinctId: userId, event: 'project_created', properties: { plan: 'pro' } });
// Feature flags
const showNewUI = await posthog.isFeatureEnabled('new-dashboard', userId);
8. Error Monitoring & Logging
| Provider | Best For | Free Tier | Cost |
|---|---|---|---|
| Sentry | Error tracking | 5K errors/mo | $26/mo |
| BetterStack | Logs + uptime | Free | $25/mo |
| Axiom | Log aggregation | 500 GB ingest/mo | $25/mo |
| Datadog | Enterprise observability | None | $15/host/mo |
Winner: Sentry for error tracking (source maps, breadcrumbs, performance). Add BetterStack or Axiom for log aggregation.
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 0.1,
environment: process.env.NODE_ENV,
});
// Errors are automatically captured
// Manual capture for business logic errors:
Sentry.captureException(new Error('Payment processing failed'), {
tags: { userId, plan: 'pro' },
});
9. AI / LLM
| Provider | Best Model | Strength | Cost (1M tokens) |
|---|---|---|---|
| Anthropic | Claude Sonnet | Coding, safety, analysis | $3 in / $15 out |
| OpenAI | GPT-4o | Ecosystem, multimodal | $5 in / $15 out |
| Gemini 2.0 Flash | Cheapest good model | $0.10 in / $0.40 out | |
| Groq | Llama 3.3 70B | Fastest inference | $0.59 in / $0.79 out |
Winner: Depends on use case. Claude for coding/analysis, GPT-4o for ecosystem/multimodal, Gemini Flash for cost-sensitive, Groq for speed.
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic();
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
});
10. Background Jobs & Cron
| Provider | Best For | Free Tier | Cost |
|---|---|---|---|
| Inngest | Event-driven workflows | 50K runs/mo | $50/mo |
| Trigger.dev | Long-running jobs | 50K runs/mo | $25/mo |
| Upstash QStash | Serverless message queue | 500 msgs/day | $1/100K msgs |
| BullMQ | Self-hosted Redis queues | Free (OSS) | Redis cost |
Winner: Inngest for serverless apps — event-driven functions, retries, cron, step functions, all without managing infrastructure.
import { inngest } from '@/lib/inngest';
// Define a background job
export const processUpload = inngest.createFunction(
{ id: 'process-upload', retries: 3 },
{ event: 'upload/received' },
async ({ event, step }) => {
const file = await step.run('download', () =>
downloadFile(event.data.fileUrl)
);
const processed = await step.run('process', () =>
processFile(file)
);
await step.run('notify', () =>
sendEmail(event.data.userId, 'Upload processed!')
);
return { processed: true };
}
);
11. Deployment & Hosting
| Provider | Best For | Free Tier | Cost |
|---|---|---|---|
| Vercel | Next.js, frontend | Hobby free | $20/mo |
| Fly.io | Containers, global | Free tier | $2-5/mo per VM |
| Railway | Full-stack, databases | 500 hrs/mo | $5/mo |
| Cloudflare Pages | Static + Workers | Generous free | $5/mo |
Winner: Vercel for Next.js apps. Fly.io if you need containers or server-side control.
12. Communication
| Channel | Provider | Free Tier | Cost Per Message |
|---|---|---|---|
| SMS | Twilio | $15 trial credit | $0.0079 (US) |
| Push | FCM | Free | Free |
| In-app | Knock / Novu | Free tier | $0.001-0.01 |
| Team | Slack webhooks | Free | Free |
The Starter Stack (Day 1)
For a new SaaS with $0 budget:
Auth: Clerk (10K MAU free)
Database: Neon (500 MB free)
Email: Resend (3K emails/month free)
Analytics: PostHog (1M events free)
Monitoring: Sentry (5K errors free)
Storage: Cloudflare R2 (10 GB free)
Hosting: Vercel (hobby free)
Payments: Stripe (no monthly fee)
Jobs: Inngest (50K runs free)
Total: $0/month
The Growth Stack (1K-10K users)
Auth: Clerk $25/month
Database: Neon + Upstash $25 + $10/month
Email: Resend $20/month
Analytics: PostHog Free-$45/month
Monitoring: Sentry + Axiom $26 + $0/month
Storage: Cloudflare R2 ~$5/month
Hosting: Vercel Pro $20/month
Search: Typesense Cloud $30/month
Payments: Stripe ~2.9% per transaction
Jobs: Inngest $50/month
Total: ~$210/month + Stripe fees
The Scale Stack (10K-100K users)
Auth: Clerk / WorkOS $100-500/month
Database: Neon Scale + Redis $50-200/month
Email: Resend / SES $50-200/month
Analytics: PostHog $100-500/month
Monitoring: Sentry + Datadog $100-500/month
Storage: Cloudflare R2 $20-100/month
Hosting: Vercel / Fly.io $100-500/month
Search: Typesense / Algolia $50-300/month
AI: Anthropic / OpenAI Usage-based
Jobs: Inngest $150-500/month
Total: $700-3,300/month + usage
Integration Architecture
// The service layer that connects everything
class AppServices {
auth: ClerkClient;
payments: Stripe;
email: Resend;
analytics: PostHog;
monitoring: Sentry;
storage: S3Client;
search: Typesense.Client;
jobs: Inngest;
// User signs up → triggers across all services
async onUserCreated(user: { id: string; email: string; name: string }) {
// 1. Create Stripe customer
const customer = await this.payments.customers.create({
email: user.email,
name: user.name,
metadata: { userId: user.id },
});
// 2. Store in database
await db.users.create({
...user,
stripeCustomerId: customer.id,
plan: 'free',
});
// 3. Index for search
await this.search.collections('users').documents().upsert({
id: user.id,
name: user.name,
email: user.email,
});
// 4. Track signup
this.analytics.capture({
distinctId: user.id,
event: 'user_signed_up',
});
// 5. Send welcome email
await this.email.emails.send({
from: 'App <hello@yourapp.com>',
to: user.email,
subject: `Welcome, ${user.name}!`,
react: WelcomeEmail({ name: user.name }),
});
}
}
Decision Framework
When choosing a provider for any layer:
| Factor | Weight | Question |
|---|---|---|
| DX | 30% | How fast can I integrate? How good are the docs? |
| Free Tier | 20% | Can I start without paying? |
| Pricing at Scale | 20% | Does it stay affordable at 10x, 100x growth? |
| Reliability | 15% | What's their uptime history? SLA? |
| Lock-in Risk | 10% | How hard is it to switch providers later? |
| Community | 5% | Is there help available when I'm stuck? |
Common Mistakes
| Mistake | Impact | Fix |
|---|---|---|
| Over-engineering day 1 | Months wasted before launch | Start with the starter stack, upgrade as you grow |
| Building auth yourself | Security vulnerabilities, weeks of work | Use Clerk or Auth.js |
| No error monitoring | Bugs in production you don't know about | Add Sentry before launch |
| Ignoring API costs | Surprise bills at scale | Model costs at 10x and 100x current usage |
| No abstraction layer | Vendor lock-in, painful migrations | Interface + adapter pattern for critical services |
| Using 20 APIs when 5 work | Integration complexity, more failure points | Consolidate where possible (PostHog replaces 3+ tools) |
Compare every API in this stack on APIScout — auth, payments, email, storage, search, analytics, and more, with pricing calculators and feature-by-feature comparisons.