Section 01 · The model
What actually happens when you create a token on Solana?
Solana does not give every token its own contract. One program, the SPL Token Program, manages every fungible token and NFT on the network, and creating a token means asking that program to set up a new mint account on your behalf.
Quick answer
In one sentence: You create an SPL token on Solana by initializing a mint account through the SPL Token Program, either with the spl token CLI or the spl token library, then creating associated token accounts and minting supply into them.
If you have worked with Ethereum, this is the first mental shift. An ERC20 token is a deployed contract with its own address and its own copy of transfer logic. A Solana token is a row of state inside a shared program. The program address never changes. What changes is the data in the accounts you create.
Three account types matter here. The mint account stores the token's global properties: total supply, decimals, and the two authorities that control it. The token account holds a balance for one wallet. The associated token account, or ATA, is a token account whose address is derived deterministically from the owner's wallet and the mint, so wallets and programs never have to guess or store an extra mapping.
This design is why Solana token operations feel fast and cheap compared to deploying a new contract per asset. You are not shipping new code. You are writing to existing programs with well understood behavior, which is also why security audits for basic token creation are rarely the bottleneck compared to the custom logic layered on top.
Token Program versus Token 2022
Most of this guide uses the original SPL Token Program, sometimes called Tokenkeg after its program ID prefix. A newer standard, Token 2022, adds optional extensions like transfer fees and confidential transfers. Use the original program unless you specifically need one of those extensions, since tooling and wallet support are more mature there.
Section 02 · The CLI path
Creating a token with the spl token command line tool
The fastest way to understand the moving parts is to create a token by hand on devnet using the command line, before you ever touch application code.
Install the Solana CLI and the spl token CLI, then point your configuration at devnet so nothing here touches real funds.
solana config set --url https://api.devnet.solana.com
solana-keygen new --outfile ~/.config/solana/id.json
solana airdrop 2The airdrop gives your local wallet devnet SOL to pay for account rent and transaction fees. Mainnet has no equivalent, which is one reason to finish your entire token flow on devnet before you spend a cent of real SOL.
Creating the mint is one command.
spl-token create-token --decimals 6This prints a new mint address. Behind that single command, the CLI builds and sends a transaction that creates an account sized for mint data, assigns it to the Token Program, and initializes it with your wallet as both the mint authority and, unless you pass a flag to disable it, the freeze authority. Six decimals mirrors USDC and most utility tokens, giving you a million units per whole token, which is granular enough for pricing without overflowing common integer types.
Next, create an associated token account and mint some supply into it.
spl-token create-account <MINT_ADDRESS>
spl-token mint <MINT_ADDRESS> 1000000The create account step derives your ATA for that mint and initializes it. The mint step increases total supply and credits your ATA, and only your wallet can run it, because your wallet holds the mint authority. Check your balance with spl-token balance <MINT_ADDRESS> to confirm the mint worked.
Section 03 · The programmatic path
Creating a token from code with the spl token library
The CLI is fine for one off tokens, but any real product needs to create or manage tokens from inside an application, which means using the spl token library directly.
The library exposes helper functions that build the same instructions the CLI sends, but you compose them yourself, which matters once token creation is triggered by a user action rather than a terminal command.
import {
Connection,
Keypair,
clusterApiUrl,
} from "@solana/web3.js";
import {
createMint,
getOrCreateAssociatedTokenAccount,
mintTo,
} from "@solana/spl-token";
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const payer = Keypair.generate();
const mintAuthority = payer;
const freezeAuthority = null;
const mint = await createMint(
connection,
payer,
mintAuthority.publicKey,
freezeAuthority,
6
);
const tokenAccount = await getOrCreateAssociatedTokenAccount(
connection,
payer,
mint,
payer.publicKey
);
await mintTo(
connection,
payer,
mint,
tokenAccount.address,
mintAuthority,
1_000_000_000
);createMint bundles the account creation and initialization into one call, and it needs a payer to cover rent, a mint authority public key, an optional freeze authority, and a decimals value. Passing null for the freeze authority is a deliberate choice: it permanently rules out freezing any holder's balance later, which is what most utility and governance tokens should do.
getOrCreateAssociatedTokenAccount is idiomatic because it checks whether the ATA already exists before trying to create it, which matters once you are minting to accounts you do not fully control, like a user's connected wallet. mintTo is the programmatic version of the CLI mint command, and note the amount is in the smallest unit, not whole tokens, so 1,000,000,000 with 6 decimals equals 1,000 whole tokens.
Section 05 · Associated token accounts
Why do you need an associated token account for every holder?
A mint only tracks total supply and metadata. Every wallet that holds the token needs its own account, and the associated token account standard makes finding that account deterministic instead of guesswork.
Without the ATA standard, a wallet or program that wanted to check a balance would need some separate registry mapping owners to token accounts, since a user could otherwise create multiple token accounts for the same mint. The ATA program derives one canonical address from the owner and the mint, so any client can compute where a balance should live without asking anyone.
This is why almost every transfer flow you will write starts with getOrCreateAssociatedTokenAccount for both sender and recipient. If the recipient has never touched your token before, their ATA does not exist yet, and someone, usually the sender or a relayer, has to pay the rent to create it. Budgeting for that extra cost is one of the more common gaps in a first Solana integration.
Section 06 · Devnet versus mainnet
What changes when you move from devnet to mainnet?
The instructions are identical. What changes is that mistakes now cost real money and, because supply and authority changes are often irreversible, real reputation.
On devnet, SOL is free through the faucet and rent is a rounding error. On mainnet, every account you create costs real SOL in rent, refundable only if you close the account, and every mint or authority change is a real transaction fee. Before you deploy to mainnet, run the entire flow end to end on devnet at least once with the exact decimals, exact authority settings, and exact initial supply you intend to ship, since changing decimals after the fact is not possible and changing authorities after revocation is not either.
Two more differences matter in practice. RPC rate limits are tighter on the public mainnet endpoint than on devnet, so any production application creating tokens or accounts on demand needs a dedicated RPC provider rather than the default public endpoint. And block explorers, wallets, and price aggregators pick up mainnet tokens automatically once they exist, which means a mistake in decimals or a forgotten freeze authority becomes visible to real users immediately rather than staying inside a test environment.
If any of this account and authority model feels unfamiliar, the earlier guide on Anchor accounts in Solana covers the same account ownership and initialization patterns from the program development side, which is the same foundation the Token Program itself is built on.
If you are about to wire this token creation flow into an actual product, the companion guide on integrating an SPL token with a Next.js application picks up exactly where this leaves off, including wallet connection, reading balances, and building a transfer UI.
FAQ
Frequently asked questions
How do I create an SPL token on Solana?
Create a mint account through the SPL Token Program using either the spl token command line tool, with a single create token command, or the spl token library's createMint function inside your application. Then create an associated token account for each holder and mint supply into it.
What is the difference between the spl token CLI and the spl token library?
The CLI is a command line tool best for testing, one off token creation, and quick devnet experiments. The spl token library is a TypeScript package you call from inside an application when token creation or management needs to happen as part of a product flow, such as a user triggered mint.
What are decimals in an SPL token and can I change them later?
Decimals set how divisible your token is, similar to cents in a dollar. Six is a common default matching USDC. Decimals are fixed permanently at mint creation and cannot be changed afterward, so choose carefully based on the smallest meaningful unit for your use case.
Why would I revoke mint authority on a token?
Revoking mint authority permanently removes the ability to create new supply, which is the standard way to prove to holders and integrators that a token has a fixed cap. It is a one way action, so only revoke it once your initial supply and distribution are final.
Do I need to set a freeze authority on my token?
Most tokens should not set a freeze authority, since it gives the authority holder the power to block any account from transferring. It is genuinely useful only for regulated assets like stablecoins that need to freeze sanctioned wallets under legal requirements.
Should I test my token on devnet before deploying to mainnet?
Yes. Devnet SOL is free and mistakes cost nothing, while mainnet requires real SOL for rent and fees and many settings, including decimals and revoked authorities, cannot be changed after the fact. Run your full creation and minting flow on devnet first.
If you are building a token that needs to plug into a product rather than sit in a wallet, the blockchain development service covers exactly this kind of Solana engineering, from token design through the application layer that surrounds it.