A full-stack app on free tiers, without a card
October 25, 2026 · 5 min read
The PSA FAU Community Forum is a moderated Q&A forum for the Pakistan Student Association community at FAU Erlangen-Nürnberg. My friend Abdul Moeez and I built it over one weekend in October 2026. At most it will have 1,000 to 1,500 users. It runs on free tiers, it costs 0 EUR today, and none of the accounts behind it has a card on file.
The only spend we plan is a domain, about 10 EUR a year. This is how the pieces fit, what each free tier quietly asks of you in return, and when I'd actually start paying. The forum is the example, but the shape works for most small apps with a frontend, a backend and some files.
Each free tier does one job
The frontend and the server functions run on Vercel Hobby. The app is Next.js 16 with the App Router; pushes to main deploy, and pull requests get preview deployments. Postgres and auth live on Supabase Free: Postgres 17, Google sign-in and email magic links, and row-level security doing the authorization.
Files go to a private Backblaze B2 bucket and reach the browser through a Cloudflare Worker. That part is designed and being built, not live yet. Auth emails leave through a Gmail account's SMTP, and Cloudflare Turnstile keeps bots away from the email sign-in. GitHub Actions does everything on a schedule: CI on every pull request, a job that keeps the database awake, and a nightly backup.
- Browser
visitors and members
- Edge worker
serves the files
100k req/daycatch: fails past the limit
- Frontend
pages + server functions
1M calls/mocatch: non-commercial only
- Bot check
guards sign-in
free
- Email
magic links
~500 mails/daycatch: needs an app password
- Database
Postgres
500 MBcatch: pauses after 7 idle days
- Auth
sign-in, sessions
50k MAUcatch: mailer: a few an hour
- Object storage
private buckets for files and backups
10 GB freeegress to Cloudflare: freecatch: past 10 GB needs a card
- Scheduled jobs
CI on every PR · keep-awake · nightly backup
free for public reposcatch: public repo: never upload a backup as an artifact
How it connects
Browser → Frontend → Database
Cache public pages, so one query serves every visitor.
Browser → Bot check → Auth → Email
Sign-in carries a bot-check token; auth verifies it and sends the link through your own SMTP.
Browser → Frontend → Object storage
Uploads go through your server with a read-write key, never straight to the bucket.
Browser → Edge worker → Object storage
Files are read through the worker with a read-only key.
Scheduled jobs → Database
Read one row every 3 days to stay awake; dump the data every night.
Scheduled jobs → Object storage
The encrypted dump goes to storage with a write-only key.
- request or data
- scheduled
Here's how the forum wires it together, with its regions and the nightly backup.
- Browser
PSA FAU members · 1,000–1,500 at most
- Media Workerin progress
workers.dev for now
100k req/day
- Next.js 16
London · lhr1
1M calls/mo
- Turnstile
guards email sign-in
free
- Gmail SMTP
magic-link emails
~500 mails/day
- Postgres 17
row-level security
500 MB - Auth
Google + magic links
50k MAU - Realtime
new notifications
- Images bucketin progress
private · stop at 8 GB
- Backups bucket
daily/ · weekly/
write-only key
- Nightly backup · 02:30 UTC
pg_dump → gzip -9 → age, then upload
free · public repokeep-awake every 3 days
How it connects
Browser → Next.js → Postgres
Public pages read through a cookieless client inside "use cache", so one result serves every visitor. Functions run in London next to the database.
Browser → Turnstile → Next.js → Auth
Email sign-in carries a Turnstile token; Supabase verifies it.
Auth → Gmail SMTP → Browser
The magic link leaves through Gmail, about 500 a day.
Postgres → Realtime → Browser
A new notification is pushed to the bell.
Browser → Next.js → Images bucket
in progress · Uploads go through a server action with the upload key.
Browser → Media Worker → Images bucket
in progress · Views go through the Worker with a read-only key.
GitHub Actions → Postgres
Every night at 02:30 UTC, pg_dump 17 through the session pooler (IPv4).
GitHub Actions → Backups bucket
gzip and age, then daily/ (and weekly/ on Sundays) with a write-only key.
- request or data
- scheduled
- in progress, not live
- in progressdesigned, being built
An account without a card fails closed
This is the idea the whole setup rests on. A free tier with a card on file can turn into a bill the month a post goes viral or a bot finds your upload form. A free tier with no card can only stop. For a student forum, a few hours of broken images is a much better failure than an invoice nobody budgeted for.
We signed up for Vercel, Supabase, GitHub, Backblaze and Cloudflare without entering a card. Backblaze is the most explicit about it: with no payment method on the account, it cannot bill, and going past the free 10 GB would need a card plus Backblaze's daily spending caps. The other official pages mostly don't say whether a card is needed at sign-up, so take this as our experience, not a guarantee.
That's also why files live on Backblaze. Cloudflare R2 has a 10 GB free tier too, but we wanted an account with no card at all, and Backblaze spelled out how that works. The limits follow the same pattern. On Vercel Hobby, going over a limit pauses that feature rather than billing. On the free Workers plan, requests past the daily limit fail instead. You accept an outage as the worst case.
Every free tier has a catch
Vercel Hobby is for personal, non-commercial use only. Ads, paid hosting or being paid to build the site count as commercial; donations don't. Inside that, you get 100 GB of Fast Data Transfer and a million function invocations a month.
Supabase Free gives you two active projects, a 500 MB database, 50,000 monthly active users and 5 GB of egress. It also pauses a project after a week without activity, and it takes no automatic backups. So we do both ourselves. One GitHub Actions job reads a single row every three days to keep the project awake. Another dumps the data every night at 02:30 UTC, encrypts it, and uploads it to Backblaze with a key that can write backups but can't read or delete them. There's a newer catch too: since September 2026 Supabase meters log ingest and log queries. It isn't enforced until early 2027, but our org once showed about 144 GB of log queries in a single day without us doing anything unusual. Worth watching now.
Supabase's built-in mailer only allows a few emails an hour, which isn't enough for magic links. Gmail SMTP needs 2-step verification and an app password, and allows roughly 500 emails a day for a normal account. That number comes from third parties, because Google doesn't publish consumer limits clearly. At our scale it's plenty, and Resend's free plan is the fallback.
Cloudflare Workers Free stops at 100,000 requests a day, resetting at 00:00 UTC, with 10 ms of CPU per request. And Backblaze B2 gives the first 10 GB of storage free, shared by everything in the account. For us that means images and backups draw from the same 10 GB. Egress is free up to three times your average monthly storage, and free to Cloudflare. The storage side has its own write-up: free image hosting with Backblaze B2 behind a Cloudflare Worker.
A few habits keep you inside the limits
Cache public pages. Ours read through a cookieless Supabase client inside Next's "use cache", so one cached result serves every visitor instead of each visit running its own function and query.
Pin functions next to the database. Supabase runs in London (eu-west-2), so the Vercel functions run in London too. Every query is a short hop instead of a trip across Europe. It's one line:
{"regions":["lhr1"]}Compress uploads in the browser, before they cost anything. In the image design, files get re-encoded to WebP, with a JPEG fallback because Safari can't encode WebP, to at most 1,600 px on the longest side and 1 MB after compression. Re-encoding drops EXIF and location data as a bonus.
Put hard caps in the database, where a bug in the frontend can't skip them. For images, Postgres triggers allow 3 images per thread, none in comments, 15 per member per day and 300 site-wide per day, and stop uploads at 8 GB in total. That leaves room for backups in the shared 10 GB.
I'd start paying when a limit stops being hypothetical
The triggers are concrete. If the forum ever makes money from ads or paid hosting, Vercel Hobby no longer fits. If images and backups head past 10 GB, the 8 GB stop kicks in first; beyond that the honest fix is a card on Backblaze with its daily spending caps set, not a cleverer cap. If the database nears 500 MB, or Supabase's log metering starts counting against us in 2027, that's the Supabase bill. If the Worker regularly hits 100,000 requests a day, images break until midnight UTC, and that's the signal for Cloudflare. Email is the one limit with a free way out: Resend's free plan comes before anything paid.
Until one of them happens, the only line in the budget is the domain.
If you're starting one tomorrow
Sign up without a card and read each provider's limits page before you rely on it; GitHub's Actions billing page is the one that confirms public repos run free on standard runners. Add the keep-awake job and the nightly dump on day one, not after the first pause. Write the caps into the database. And decide in advance which limit you'd pay to lift first, so the day it happens is a decision instead of a surprise. The workflows are all in the public repo.