Building My Own Backend for DeckDen Taught Me This
How building DeckDen with Next.js, FastAPI, and PostgreSQL taught me that owning every layer of your backend changes how you actually understand your entire stack.
7 min read

Building My Own Backend for DeckDen Taught Me This
My last project ran on Supabase, and it worked — auth, database, permissions, all handled by a platform doing the heavy lifting behind the scenes. That project is actually what pushed me to build DeckDen differently: I wanted to know what was really happening under all that convenience. So for DeckDen, I built the backend myself — FastAPI, PostgreSQL, SQLAlchemy, no platform doing the hard parts for me. That decision ended up teaching me more about how a real stack works than anything else I've built.
What I thought going in
Coming off a project where auth was basically a function call, I figured building my own backend meant writing a few routes and a schema, then wiring them up to a frontend. I didn't think it would be that different. I was wrong almost immediately.
What DeckDen actually made me learn
Once I was writing the auth, the database, and the deployment myself, an entire layer of decisions showed up that I'd genuinely never had to think about before:
Password hashing — choosing bcrypt specifically because it's slow on purpose, and understanding why that slowness is the entire point of storing a password safely
Session management — issuing my own JWTs, picking an expiry window, deciding exactly what data lives inside the token
Password resets — generating a high-entropy token, hashing it differently than a password (fast and deterministic, not salted, because a reset lookup needs an exact match), and making sure a used token can never be replayed
Cascading deletes — when a user deletes their account, making sure their decks, cards, and reset tokens actually disappear with them instead of becoming orphaned rows
CORS — learning that "the frontend can talk to the backend" isn't automatic, it's a per-environment configuration decision, and getting it wrong either breaks the app or opens it up
Environment and secrets — SECRET_KEY, database URLs, API keys, all needing to live differently in local Docker versus production, none of it hardcoded
Deploying two real services — a Railway Postgres instance and a Railway API service that have to be told how to find each other, instead of one dashboard doing it for me
Testing that it actually works — writing pytest and Vitest suites, because clicking through it once was never going to be good enough
Why this actually mattered
The password reset flow is the clearest example of what changed in how I think. My first instinct was to hash the reset token exactly like a password, because "hashing is hashing." It took sitting with why bcrypt exists — the deliberate slowness, the random salt — to realize that same salt makes an exact-match database lookup on a token impossible. Getting that wrong, and then figuring out why it was wrong, taught me more about security primitives than any tutorial had.
The same thing happened with CORS errors that only showed up in production, and with a cascading-delete bug that forced me to actually understand what cascade="all, delete-orphan" was doing in SQLAlchemy instead of just pasting it in because it looked right. Every one of those moments had the same shape: I thought I understood something, and building it myself proved I didn't — yet.
What this opened up for me
DeckDen didn't just teach me FastAPI or PostgreSQL. It taught me to actually own the pieces I used to treat as invisible — the hashing, the tokens, the CORS config, the deploy. Now when I look at an env variable or a cascade rule, I know why it's there, not just that it needs to be.
If you're a junior dev who's only ever shipped on a platform that handles the backend for you: that's not wasted time, but it's not the full picture either. Build one thing where you own every layer yourself — badly, at first. You'll find out fast exactly which parts you only ever understood secondhand.

