Tanisha fonsecaSolana's Account Model Explained for Web2 Developers If you're coming from web...
If you're coming from web development, Solana's account model is probably the first thing that will genuinely confuse you and then, once it clicks, the first thing that will genuinely impress you.
Let me save you a few days of head-scratching.
Before diving into the technical details, here's an analogy that will carry you a long way:
Solana is a filesystem.
Every account is a file. Each file has metadata (owner, permissions, size) and contents (data). Programs are like executable files chmod +x style. Data accounts are the documents those programs read and write. And the System Program? That's the kernel. It creates files, manages ownership, and handles the lowest-level operations.
Keep that mental model handy. We'll come back to it.
In Ethereum, there's a distinction between "externally owned accounts" (wallets controlled by private keys) and "contract accounts" (smart contracts). Different types, different rules.
Solana doesn't do that.
Everything is an account. Your wallet? An account. A smart contract (called a "program" in Solana)? An account. The token balance you hold? Stored in... an account. All of this lives in one giant flat key-value store where:
Simple. Uniform. Powerful.
Pop open a Solana account in the CLI and you'll see something like this:
$ solana account 11111111111111111111111111111111
{
"lamports": 1000000000,
"data": "",
"owner": "NativeLoader1111111111111111111111111111111",
"executable": true,
"rentEpoch": 18446744073709551615
}
Every single account on Solana — whether it's a wallet, a program, or a piece of stored state — has exactly these five fields:
lamports
This is the SOL balance, but measured in the smallest unit: lamports. 1 SOL = 1,000,000,000 lamports (one billion). Think of it like wei to ether, or satoshis to bitcoin. It's just a u64 integer under the hood.
data
A raw byte array. This is where the interesting stuff lives. For wallets, it's empty. For programs, it holds compiled bytecode. For data accounts (more on those in a moment), it holds whatever state the owning program decides to write there.
owner
The program address that "owns" this account. This is the key to Solana's security model: only the owner program can modify this account's data or debit its lamports. Anyone can add lamports (credit), but only the owner can take them away or change the data.
executable
A boolean. true means this account holds a deployable program. false means it's a data/state account. Once set to true, the data becomes immutable — you can't accidentally overwrite a running program.
rentEpoch
This field is deprecated. You'll always see it set to the max u64 value (18446744073709551615). Ignore it — it's a legacy artifact from how rent collection used to work.
Here's Solana's security model in two sentences:
That's it. That's the whole access control system.
In web2 terms: the owner is like a Unix file owner with exclusive write permissions. Other programs can look, but they can't touch unless they own it.
This is why, when you interact with a Solana program (say, a DeFi protocol), you have to sign a transaction that authorizes that program to act on accounts you own. The program can only write to accounts where it is listed as owner — it can never reach into your wallet uninvited.
This is the concept that trips up almost every Web2 developer the first time.
In most backend frameworks, state lives inside the application. Your Node.js server has in-memory state, or it queries a database it owns. Either way, the program and its data are tightly coupled.
On Solana, programs are stateless.
A Solana program stores its compiled code in one account (marked executable: true). Any data it needs to track — user balances, game state, protocol configuration — lives in completely separate accounts that the program owns.
The analogy: imagine a REST API (the program) that never stores anything locally. Every request reads from and writes to a database (the data accounts). The API logic and the database are cleanly separated. The "database" is owned by the API, but the data itself lives outside the code.
In practice, this means when you call a Solana program, you have to tell it which accounts to read and write. You pass them in as part of the transaction. The program can't go looking for its own data — you have to bring it.
This feels weird at first. Then you realize it's what makes Solana blazing fast: the runtime knows exactly which accounts a transaction will touch before it even executes, so it can parallelize transactions that don't share accounts.
Every account occupies space on every Solana validator in the world. That's not free.
To keep an account alive on-chain, it must hold a minimum lamport balance proportional to the size of its data. This is called being rent-exempt.
For a basic account with no extra data, the threshold is roughly 0.00089 SOL (about $0.10–$0.20 at most price ranges). Accounts above this threshold stay on-chain indefinitely. Accounts below it... don't exist in the first place, because modern Solana tooling simply won't let you create underfunded accounts.
You can check the exact minimum for any given data size:
# Check rent for a 0-byte account
$ solana rent 0
# Output:
# Rent-exempt minimum: 0.00089088 SOL
Or via RPC:
curl https://api.mainnet-beta.solana.com -X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"getMinimumBalanceForRentExemption","params":[0]}'
The larger the account (more bytes in data), the higher the minimum balance required. Close the account, reclaim the lamports — the space is yours to rent, not buy forever.
Here's the mental model, fully assembled:
| Solana Concept | Filesystem Analogy |
|---|---|
| Account | File |
data field |
File contents |
owner field |
File owner (Unix permissions) |
executable: true |
Executable binary (chmod +x) |
| Program account | Application binary |
| Data account | Data file read/written by the app |
| System Program | OS kernel |
| Lamports | Disk quota |
When you deploy a Solana program, you're writing an executable file to the filesystem. When that program creates accounts to track state, it's creating data files it owns. When users interact with it, they're running the binary and pointing it at the right files.
The account model isn't arbitrary. It's designed for performance and parallelism.
Because every transaction must declare its accounts upfront, the Solana runtime can look at two transactions and immediately know whether they can run in parallel (different accounts) or need to be serialized (same accounts). This is how Solana achieves the throughput it does — it's not just hardware, it's the data model.
State separation also means programs are more composable. One program can pass an account it owns to another program, delegating access in controlled ways. The whole DeFi ecosystem on Solana is built on programs handing account authority back and forth.
Before you write your next line of Solana code, be able to answer these questions:
executable: true and executable: false?If you can answer those confidently, you understand the account model. Everything else tokens, NFTs, PDAs, CPIs — is built on top of exactly this foundation.
This article is part of my #100DaysOfSolana journey. If you're on a similar path, drop a comment always happy to compare notes.