If you're coming from a Web2 background, one of the first things that feels strange about Solana is that applications don't always create accounts using private keys.
Instead, they often use something called a "Program Derived Address (PDA)".
At first, that sounded complicated to me.
After building several Anchor programs during my #100DaysOfSolana challenge, I realized PDAs aren't magic at all they solve a problem that every backend developer already understands.
Let's look at them through a Web2 lens.
How We Usually Think in Web2
Imagine you're building a SaaS application.
You have a table like this:
| User ID | Counter |
|---|---|
| 101 | 5 |
| 205 | 12 |
| 318 | 0 |
Whenever a request arrives, you already know the user's ID.
You don't generate a random database key every time. Instead, you derive which row belongs to the user.
Your application always knows exactly where that user's data lives.
The Problem on Solana
My first Anchor counter program didn't work like that.
To create a counter, I generated a brand new keypair for the account. That worked... but it meant the client had to remember that keypair forever.
Lose it, and you lose the ability to easily locate your counter account.
That approach is fine for tutorials but not for real applications.
Enter Program Derived Addresses
A PDA is an account whose address is deterministically derived from:
- one or more seeds
- your program ID
- a bump value For example:
seeds = [
b"counter",
user.key().as_ref(),
]
Every time the same user calls the program, Anchor derives the exact same address.
No database lookup.
No random account generation.
No extra storage needed to remember where the account lives.
The Web2 Analogy
Imagine this function:
getCounter(userId)
Internally your backend might do:
SELECT *
FROM counters
WHERE user_id = ?
The user ID uniquely identifies the row.
PDAs work almost the same way.
Instead of looking up a database row, Solana derives an account address from predictable inputs.
It's closer to computing a deterministic primary key than generating a UUID.
Why This Is Powerful
Suppose Alice opens your app.
Anchor derives:
("counter", Alice)
Bob opens the app.
Anchor derives:
("counter", Bob)
Both users automatically get different accounts.
No collisions.
No bookkeeping.
Your program always knows where each user's state belongs.
Where Anchor Helps
One thing I really appreciate about Anchor is how much boilerplate disappears.
Instead of manually checking addresses, ownership, and account creation, you simply declare constraints:
#[account(
init,
payer = user,
seeds = [b"counter", user.key().as_ref()],
bump
)]
Anchor then:
- derives the PDA
- computes the canonical bump
- creates the account
- allocates storage
- makes the program sign for it
All before your instruction handler even runs.
Security Comes from Constraints
Another thing that clicked for me was that authorization often lives in account constraints rather than business logic.
For example:
#[account(
has_one = user
)]
or
#[account(
constraint = !config.paused
)]
Instead of writing lots of validation code inside the handler, Anchor verifies everything first.
If validation fails, the transaction never reaches your business logic.
As a backend developer, it reminded me of middleware that rejects unauthorized requests before your controller executes.
The Bigger Picture
One thing the Solana journey has taught me is that blockchain development isn't about throwing away Web2 knowledge.
It's about applying familiar backend concepts in a different environment.
Database rows become accounts.
Primary keys become deterministic addresses.
Middleware becomes account constraints.
Tables become on-chain state.
Once I started viewing Solana through concepts I already understood, everything became much easier to reason about.
What I'm Building
This article is based on one of the programs I built during my #100DaysOfSolana challenge.
The project evolved from:
- a simple counter
- to stateful accounts
- to authorization with
has_one - to negative testing with LiteSVM
- to per-user PDAs
- to configuration PDAs
- to reclaiming rent by closing PDA accounts
Each step felt surprisingly familiar once I translated it into Web2 concepts.
Final Thoughts
If you're a Web2 developer curious about Solana, don't start by trying to memorize blockchain terminology.
Instead, ask:
"What problem is this solving that I already solve every day?"
More often than not, there's a familiar backend concept hiding underneath.
That's what finally made PDAs click for me.
Thanks for reading!
I'm documenting my learning journey through #100DaysOfSolana, sharing what I build and translating blockchain concepts into language that backend developers already understand.
If you're learning Solana too, I'd love to connect and learn together.
Top comments (0)