Let me start with a confession.
When I first heard "everything on Solana is an account," I nodded like I understood. I did not understand. I just did not want to look confused.
It took me actually running commands in the terminal, seeing things break, reading error messages I did not expect, and sitting with the output until it clicked. That is what this post is about. Not the polished explanation. The actual journey.
Forget your database mental model first
Coming from Web2, my brain was wired to think in tables. You have a users table, a transactions table, maybe a products table. Each one has columns. Each row is a record. Data and code live completely separately.
Solana does not work like that.
On Solana, everything is an account. Your wallet is an account. A smart contract is an account. The token you hold is an account. The metadata of that token is an account. All of them. Every single thing on the network is described by the same five fields.
I know that sounds weird. Keep reading.
The five fields that describe everything
When I ran solana account against my own devnet wallet, here is what came back:
Public Key: CN9aDJfMzzQiR7mFGZCVbJHXKjdVAAiZJsEsmVTS3ZQo
Balance: 0.00158688 SOL
Owner: 11111111111111111111111111111111
Executable: false
Rent Epoch: 18446744073709551615
Let me break down what each of these actually means in plain terms:
Lamports (Balance): The SOL balance stored in the account. 1 SOL equals exactly one billion lamports. The network always works in lamports internally.
Data: A raw byte array. For a basic wallet this is zero bytes because wallets do not store custom data. For a smart contract account this contains compiled program code.
Owner: The program that has authority over this account. See that long string of ones? That is the System Program. It is Solana's root-level kernel. It owns every regular wallet on the network.
Executable: A simple true or false. If true, the bytes in the data field are treated as runnable program code. If false, it is just storage.
Rent Epoch: A legacy field from when Solana charged ongoing rent for storage. That system is deprecated now. For rent-exempt accounts it just shows a very large number. You can mostly ignore it.
The thing that actually broke my Web2 brain
Here is the part that tripped me up the most.
In Ethereum and in traditional backends, code and data are often coupled. A smart contract manages its own internal storage. You deploy the contract and the storage comes with it.
On Solana, programs are completely stateless.
The program account holds code. A separate data account holds state. They are two different accounts. The program owns the data account, meaning only that program can write to it. When you call a program, you explicitly pass in every account it will need to read from or write to during that transaction.
The analogy that finally made it click for me: think of a Solana program like a web server. The server runs code but it does not store your user photos inside its own binary. It reads from and writes to external storage. The program is the server. The data accounts are the storage.
This separation is also what makes Solana fast. Because you declare every account a transaction will touch upfront, validators know in advance which pieces of state are being used. Transactions that touch different accounts can run in parallel without stepping on each other.
The error that taught me more than any tutorial
I wanted to create an account manually with 100 bytes of storage. I found a command in some tutorial and ran it:
solana create-account ...
My terminal responded with:
error: The subcommand 'create-account' wasn't recognized
Did you mean 'create-stake-account'?
Web3 tooling moves fast. Tutorials get stale. That is just the reality.
But the error pushed me to understand the actual underlying mechanic. An account on Solana does not exist until it holds lamports. Because validators store the entire network state in RAM for speed, you have to pay for the space you occupy. This deposit is called being rent-exempt.
I ran this to find out exactly how much 100 bytes would cost:
solana rent 100
The answer was 0.00158688 SOL. Then I funded the address directly:
solana transfer CN9aDJfMzzQiR7mFGZCVbJHXKjdVAAiZJsEsmVTS3ZQo 0.00158688 --allow-unfunded-recipient --url devnet
The transaction confirmed, the System Program recognized the incoming lamports, and the account came to life on the ledger. No special creation command needed. Just meeting the minimum balance requirement.
That one broken command taught me more about how Solana actually works than three hours of reading documentation did.
What I am carrying forward from this
Just three things:
Programs and data are always separate. Get comfortable with that. It is very different from how most Web2 backends are structured but once it clicks it makes sense.
Space is a financial decision. When you build on Solana you cannot just add columns to a database and call it a day. Every byte of on-chain storage costs real tokens. You think carefully about your data layout before you deploy.
When CLI commands break, drop to the fundamentals. Do not spend an hour looking for the right command. Understand what you are actually trying to do at the network level, then find the simplest path to accomplish it.
I am still learning. Some days the terminal cooperates and some days it absolutely does not. But I understand a lot more about what is happening under the hood than I did two weeks ago.
If you are also on this journey and something I said clicked or confused you, say so in the comments. I read them.
Top comments (0)