As a backend developer, I came into Solana thinking transactions were basically API requests.
You send some data, the network processes it, and you get a success or failure response.
Technically that's not completely wrong.
But after building my first transfer tool during the MLH 100 Days of Solana challenge, I realized that mental model breaks down pretty quickly.
The Web2 Mental Model
Most of us are used to something like this:
await fetch("/api/transfer", {
method: "POST",
body: JSON.stringify({
recipient: userId,
amount: 100,
}),
});
The server receives the request, checks permissions, updates a database, and sends back a response.
The server is trusted.
The database is trusted.
Everything happens inside infrastructure controlled by a single organization.
What Actually Happens On Solana
A Solana transaction is much closer to a signed instruction package than an API request.
When I built a CLI tool to transfer SOL, the process looked more like this:
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) =>
appendTransactionMessageInstruction(
getTransferSolInstruction({
source: sender,
destination: recipient,
amount: transferLamports,
}),
tx )
);
Before anything reaches the network, I have to:
- Define the instruction
- Specify who pays the fee
- Add a recent blockhash
- Sign the transaction with my private key
Only then can it be submitted.
Unlike a typical API call, the network doesn't trust me just because I connected to it. I have to cryptographically prove I am authorized to perform the action.
The Part That Surprised Me
What surprised me most was transaction confirmation.
In Web2, a successful response usually means you're done.
On Solana, there are stages.
A transaction moves through commitment levels:
Processed
↓
Confirmed
↓
Finalized
When I upgraded my transfer tool, I started tracking these stages explicitly:
await waitForCommitment(rpc, signature, "confirmed");
await waitForCommitment(rpc, signature, "finalized");
This gave me output like:
Status: Sending transaction...
Status: Processed
Status: Confirmed
Status: Finalized
That felt much closer to watching a distributed system reach consensus than waiting for an API response.
Where The Database Analogy Still Works
One thing that felt familiar was atomicity.
Like a database transaction, a Solana transaction is all-or-nothing.
Either every instruction succeeds, or the entire transaction fails.
There is no partial success.
But unlike a database transaction, Solana transactions must also be signed, broadcast to a decentralized network, voted on by validators, and confirmed before they're considered final.
That's where the analogy stops being useful.
My Biggest Takeaway
The biggest mental shift for me was realizing that a Solana transaction isn't a request asking a server to do something.
It's a signed statement saying:
"I authorize these exact state changes."
The network then verifies that statement, executes it, and reaches consensus on the result.
That sounds like a small distinction, but it completely changes how you think about application architecture.
As a Web2 developer learning Solana, that was the moment transactions finally clicked for me.
Top comments (0)