Skip to main content
Part of the How to land transactions on Solana guide.
TLDR:
  • Priority fees on Solana let you attach a higher compute unit price to your transactions, boosting confirmation speed.
  • They’re especially useful during network congestion or in time-critical situations like NFT drops or rapid trading.
  • This guide shows how to implement priority fees in a TypeScript/Node.js setup, leveraging the Compute Budget Program.
  • By tweaking the microLamports per compute unit, you can ensure your most critical transactions are processed first.

Main article

Transaction speed and efficiency are crucial factors that can make or break user experiences in blockchain. While the Solana network is known for its high throughput and low latency, there may be times when you need to prioritize your transactions over others, especially during periods of high network congestion. This is where priority fees come into play. Priority fees on Solana allow users to attach a higher fee to their transactions, incentivizing validators to process them more quickly. By setting a higher compute unit price, your transaction gains priority over those with lower fees, ensuring faster confirmation times. This feature is particularly valuable for time-sensitive operations, such as trading on decentralized exchanges or participating in high-demand events like NFT mints. In this tutorial, we’ll dive into the concept of priority fees on Solana, exploring how they work and why they are a valuable tool for developers and users alike. We’ll walk through a practical example with TypeScript, showing it in both Solana JavaScript libraries side by side — @solana/kit (the newer, tree-shakable, functional SDK, formerly @solana/web3.js v2) and the classic @solana/web3.js (the Connection/PublicKey API) — both of which are actively maintained. By the end of this guide, you’ll have a solid understanding of priority fees and the ability to leverage them to enhance the performance of your Solana-based projects.

Understand Solana Priority Fees

Priority fees on Solana are optional fees, priced in micro-lamports per Compute Unit (very small amounts of SOL). These fees can be appended to transactions to incentivize validator nodes to prioritize and include them in blocks more quickly. They come in addition to the base transaction fee of 5000 lamports per signature. When the network is congested with transactions carrying priority fees, validators are economically incentivized to schedule and process transactions with higher fees per compute unit first, ensuring optimal resource utilization. Users can implement priority fees using the Compute Budget Program to modify the compute unit limit and set a compute unit price for their transactions. The higher the compute units required for a transaction, the more fees will be paid when priority fees are added.

Implement Priority Fees with a practical example

This project aims to provide a practical demonstration of how to implement priority fees in Solana transactions. The code showcases a simple Solana transaction that transfers SOL from one account to another with the addition of a priority fee. The example uses the Compute Budget Program to set a compute unit price, which attaches the priority fee. The priority fee is compute_unit_price × compute_unit_limit, so in production you should also cap the compute units with a compute-unit-limit instruction sized to what the transaction actually consumes — ideally from a live simulation. The @solana/kit version does this with estimateComputeUnitLimit; sizing the limit accurately both improves landing and avoids overpaying.

Prerequisites

Before diving into the code and practical implementation, ensuring you have several vital prerequisites is essential. This foundation will set you up for success, enabling a smooth development experience. Let’s go through what you need:

Deploy a Chainstack Solana node

Deploy a reliable Solana RPC endpoint:

Sign up with Chainstack

Deploy a node

View node access and credentials

Set up your environment

  • Node.js: Make sure your machine has Node.js (version 18 or higher) installed. Node.js is a prerequisite for running the scripts and managing the project’s dependencies.
  • npm: The Node Package Manager (npm) is the default package manager for Node.js projects. It will be used to install the necessary dependencies for this project. npm comes pre-installed with Node.js, so you don’t need to install it separately.
  • Solana wallet: You’ll need a Solana wallet with SOL.
If you prefer, you can use Yarn as an alternative package manager. Yarn is a fast, reliable, and secure dependency management tool. After installing Node.js, you can install Yarn globally by running the following command in your terminal:npm install --global yarn

Initialize a TypeScript project

To get started, we need to set up a TypeScript project. This will give us a structured environment for our code and enable us to leverage TypeScript’s features, such as type-checking and other enhancements. Follow these steps to create a new TypeScript project:
  • Create a project directory: Open your terminal and navigate to the location where you want to create your project directory. Run the following command to create a new directory:
mkdir solana-priority-fees
  • Initialize a new Node.js project: Navigate into the newly created directory and run the following command to initialize a new Node.js project:
cd solana-priority-fees
npm init -y
This command will create a package.json file to store information about your project and its dependencies.
  • Install TypeScript: With your Node.js project initialized, you can now install TypeScript as a development dependency. Run the following command:
npm install --save-dev typescript
This will add TypeScript to your project’s dependencies and create a node_modules folder with the required packages.
  • Create a TypeScript configuration file: To configure TypeScript for your project, you must create a tsconfig.json file. Run the following command to generate a basic configuration file:
npx tsc --init
This command will create a tsconfig.json file in your project directory with default settings. You can customize these settings as needed for your project. After completing these steps, a TypeScript project will be set up and ready for development. You can start writing TypeScript code in your project directory, and the TypeScript compiler will automatically check for type errors and compile your code.
  • Create a source file: Let’s create our first TypeScript file where we’ll write our code.
touch main.ts

Install required packages

To interact with the Solana blockchain, we must install a few packages. This guide shows two Solana JavaScript libraries side by side — both are actively maintained — so install the set for whichever you choose. dotenv (loads environment variables) and ts-node (runs TypeScript directly) are used by both.
Bash
npm install @solana/kit @solana-program/compute-budget @solana-program/system dotenv
npm install --save-dev ts-node
  • @solana/kit — the newer, tree-shakable, functional SDK. It also handles base58 encoding/decoding, so no separate bs58 package is needed.
  • @solana-program/compute-budget — Compute Budget Program instructions to set the compute unit price (the priority fee) and limit.
  • @solana-program/system — System Program instructions, including the SOL transfer used in this example.
Your package.json should then include:
JSON
"dependencies": {
  "@solana/kit": "^7.0.0",
  "@solana-program/compute-budget": "^0.15.0",
  "@solana-program/system": "^0.12.0",
  "dotenv": "^16.4.5"
}
With these packages installed, you’ll have the tools to connect to a Solana node, manage a wallet, and send a transaction with a priority fee using TypeScript. In the next section, we’ll start coding.

Set up your environment variables

This tutorial will use sensitive information such as private keys and RPC node URLs. It’s crucial to keep this information secure and avoid committing it to version control systems like Git. We’ll use the dotenv package to load environment variables from a .env file to achieve this. Follow these steps to set up your environment variables:
  • Create a .env file: In the root directory of your project, create a new file called .env. This file will store your environment variables.
  • Add your environment variables: Open the .env file and add the following variables, replacing the placeholders with your actual values:
SOLANA_RPC="YOUR_HTTPS_CHAINSTACK_URL"
SOLANA_WSS="YOUR_WEBSOCKET_CHAINSTACK_URL"
PRIVATE_KEY="YOUR_PRIVATE_KEY"
  • SOLANA_RPC: This variable should contain your Solana node’s HTTP RPC URL. If you’re using a Chainstack node, the RPC URL is in the node’s credentials.
  • SOLANA_WSS: This variable should contain the WebSocket URL of your Solana node. If you’re using a Chainstack node, you can find the WebSocket URL in the node’s credentials.
  • PRIVATE_KEY: This variable should contain the private key of the Solana wallet you want to use for token transfers.

How to use environment variables

Once the .env file is set up, you can load environment variables in your TypeScript code (e.g., main.ts), import the dotenv package, and load the environment variables at the beginning of your script:
import "dotenv/config";
This will load the environment variables from the .env file into the process.env object, allowing you to access them using process.env.VARIABLE_NAME. Access environment variables: You can now access the environment variables in your code like this:
const rpcUrl = process.env.SOLANA_RPC;
const wsUrl = process.env.SOLANA_WSS;
const privateKey = process.env.PRIVATE_KEY;
By following this approach, you can keep sensitive information like private keys and node URLs out of your codebase, making it more secure and easier to manage different environments (e.g., development, staging, production).
Remember to add the .env file to your .gitignore file to prevent it from being committed to version control systems, as it contains sensitive information.

Send Solana transactions with priority fees in this code walkthrough

Now that we have set up the project, installed the required packages, and configured the environment variables, it’s time to put everything together and implement the code.

Add the code

  1. Open the main.ts file you created earlier in your preferred code editor.
  2. Paste the following code into the main.ts file:
TypeScript
import {
  createSolanaRpc, createSolanaRpcSubscriptions, lamports, pipe,
  createKeyPairSignerFromBytes, getBase58Encoder,
  createTransactionMessage, setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions,
  estimateComputeUnitLimitFactory, signTransactionMessageWithSigners,
  sendAndConfirmTransactionFactory, getSignatureFromTransaction,
} from "@solana/kit";
import {
  getSetComputeUnitPriceInstruction, getSetComputeUnitLimitInstruction,
} from "@solana-program/compute-budget";
import { getTransferSolInstruction } from "@solana-program/system";
import "dotenv/config";

const rpc = createSolanaRpc(process.env.SOLANA_RPC!);
const rpcSubscriptions = createSolanaRpcSubscriptions(process.env.SOLANA_WSS!);

// Config priority fee and amount to transfer
const PRIORITY_RATE = 25000; // micro-lamports per compute unit
const AMOUNT_TO_TRANSFER = lamports(1_000_000n); // 0.001 SOL (1 SOL = 1_000_000_000 lamports)

async function sendTransactionWithPriorityFee() {
  // Load the fee payer from a base58-encoded secret key. @solana/kit decodes base58
  // with getBase58Encoder, so no separate bs58 package is needed.
  const signer = await createKeyPairSignerFromBytes(
    getBase58Encoder().encode(process.env.PRIVATE_KEY!)
  );
  console.log(`Initial Setup: Public Key - ${signer.address}`);

  // Get the latest blockhash at the confirmed commitment
  const { value: latestBlockhash } = await rpc
    .getLatestBlockhash({ commitment: "confirmed" })
    .send();
  console.log(" ✅ - Fetched latest blockhash. Last valid height:", latestBlockhash.lastValidBlockHeight);

  // Build the transaction message: attach the priority fee (compute unit price)
  // and the self-transfer instruction.
  const draftMessage = pipe(
    createTransactionMessage({ version: 0 }),
    (m) => setTransactionMessageFeePayerSigner(signer, m),
    (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
    (m) => appendTransactionMessageInstructions([
      getSetComputeUnitPriceInstruction({ microLamports: PRIORITY_RATE }),
      getTransferSolInstruction({
        source: signer,
        destination: signer.address,
        amount: AMOUNT_TO_TRANSFER,
      }),
    ], m),
  );
  console.log(" ✅ - Built transaction message");

  // Size the compute unit limit from a live simulation (~10% margin), then set it.
  // The priority fee you pay is compute_unit_price × compute_unit_limit, so an
  // accurate limit improves landing and avoids overpaying.
  const estimatedUnits = await estimateComputeUnitLimitFactory({ rpc })(draftMessage);
  const message = appendTransactionMessageInstructions(
    [getSetComputeUnitLimitInstruction({ units: Math.ceil(estimatedUnits * 1.1) })],
    draftMessage,
  );
  console.log(` ✅ - Estimated compute units: ${estimatedUnits}`);

  // Sign the transaction
  const signedTransaction = await signTransactionMessageWithSigners(message);
  const signature = getSignatureFromTransaction(signedTransaction);
  console.log(" ✅ - Transaction signed");

  console.log(`Sending ${Number(AMOUNT_TO_TRANSFER) / 1e9} SOL from ${signer.address} to ${signer.address} with priority fee rate ${PRIORITY_RATE} micro-lamports`);

  try {
    // Send and confirm over websockets against the blockhash + lastValidBlockHeight.
    // sendAndConfirmTransactionFactory replaces the deprecated confirmTransaction.
    await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
      signedTransaction, { commitment: "confirmed" }
    );
    console.log("🚀 Transaction Successfully Confirmed!", "\n", `https://solscan.io/tx/${signature}`);
  } catch (error) {
    console.error(error);
  }
}

// Call the function to send the transaction with a priority fee
sendTransactionWithPriorityFee();
Here is a breakdown of the code. Both versions do the same work — connect, set the priority fee, build a transaction, sign it, and send it — and differ only in API shape (@solana/kit is functional and asynchronous; @solana/web3.js is object-oriented).

Initialize the connection and account

  • Connection: @solana/kit creates an RPC client with createSolanaRpc (plus createSolanaRpcSubscriptions for the websocket confirmation); @solana/web3.js creates a single new Connection with the WSS endpoint and commitment. Both read the RPC/WSS endpoints from your environment.
  • Account: Both decode the base58 private key from the environment variable. @solana/kit uses getBase58Encoder + createKeyPairSignerFromBytes to build a TransactionSigner (no bs58 package); @solana/web3.js uses bs58.decode + Keypair.fromSecretKey.

Configure transaction details

  • Priority fee and transfer amount: Both set a priority fee rate in micro-lamports and a transfer amount. @solana/kit expresses the amount as a lamports(...) value; @solana/web3.js multiplies by LAMPORTS_PER_SOL. The priority fee adjusts the compute unit price to influence processing speed.
  • Transaction instructions: Both attach a compute-unit-price instruction (the priority fee) and a SOL transfer. @solana/kit uses getSetComputeUnitPriceInstruction and getTransferSolInstruction; @solana/web3.js uses ComputeBudgetProgram.setComputeUnitPrice and SystemProgram.transfer. The @solana/kit version additionally sizes and appends a compute-unit-limit instruction after simulating (see below).
In this example, the micro-lamport amount is arbitrary, but you can calculate it more dynamically using the getRecentPrioritizationFees method

Construct and send the transaction

  • Fetch the latest blockhash: Both retrieve the most recent blockhash at the confirmed commitment. It ties the transaction to a recent point in the chain’s history, and its lastValidBlockHeight bounds how long the transaction stays valid.
  • Build the message: @solana/kit composes a version 0 message with the pipe helper (fee payer signer, blockhash lifetime, instructions); @solana/web3.js builds a TransactionMessage and calls .compileToV0Message(), then wraps it in a VersionedTransaction.
  • Size the compute unit limit (@solana/kit): estimateComputeUnitLimitFactory simulates the transaction against the node to measure the compute units it consumes, then sets the limit to that value plus a ~10% margin. Sizing the limit accurately is recommended in both SDKs; the classic example omits it for brevity.
  • Sign the transaction: @solana/kit uses signTransactionMessageWithSigners; @solana/web3.js calls transaction.sign([FROM_KEYPAIR]).
  • Submit and confirm: @solana/kit uses sendAndConfirmTransactionFactory, which confirms over websockets against the blockhash and lastValidBlockHeight. @solana/web3.js calls sendTransaction then confirmTransaction with the blockhash and lastValidBlockHeight (the current form — the older single-signature confirmTransaction(signature) overload is the deprecated one).
  • Logging and error handling: Both log key milestones and wrap submission in a try/catch so failures are reported.

Run the script with Priority Fees

After familiarizing ourselves with the code, it’s time to execute a Solana transaction incorporating a priority fee for faster processing. By default, this script transfers 0.001 SOL from the sender’s account to the same account, demonstrating the application of a priority fee. You can adjust the recipient, the priority fee rate, and the transfer amount by modifying these lines:
TypeScript
// Config priority fee and amount to transfer
const PRIORITY_RATE = 25000; // Adjust the priority fee rate in micro-lamports here

const AMOUNT_TO_TRANSFER = lamports(1_000_000n); // Change the transfer amount here (in lamports)

// To send to another wallet, import `address` from @solana/kit and set the
// transfer destination to address("RECIPIENT_ADDRESS") instead of signer.address.
To execute the script after setting up your desired parameters, run the following command in your terminal:
ts-node main.ts
This will initiate the transaction with the applied priority fee, logging the process to the console. The output will resemble the following:
Shell
$ ts-node main.ts

Initial Setup: Public Key - CzNGm14nMopjGYyycMbWqEF2e1aEHcJLKk2CHw9BiZwC
 - Fetched latest blockhash. Last valid height: 235678920
 - Built transaction message
 - Estimated compute units: 300
 - Transaction signed
Sending 0.001 SOL from CzNGm14nMopjGYyycMbWqEF2e1aEHcJLKk2CHw9BiZwC to CzNGm14nMopjGYyycMbWqEF2e1aEHcJLKk2CHw9BiZwC with priority fee rate 25000 micro-lamports
🚀 Transaction Successfully Confirmed!
 https://solscan.io/tx/4iJ6MZQ8kBBp4KeZrcrm9fkfL92mccbgD6uMFu84iNkxSi589E1yw4fbpHUcpEk3LhtDYQ76vjbyNQaG52TSaWfT
Here, you can find a transaction example on Solscan. You can see the applied priority fee under Instruction Details > #2 - Compute Budget: Set Compute Unit Price.

Conclusion

In this guide, we’ve explored the concept of priority fees on the Solana blockchain, demonstrating their significance and how they can be utilized to ensure faster transaction processing times, particularly during periods of high network congestion. You’ve learned about the mechanics of priority fees, including how they incentivize validators with higher fees for quicker transaction confirmations. Through a practical example, we’ve walked you through implementing priority fees in your Solana transactions in TypeScript, using both @solana/kit and the classic @solana/web3.js. By adjusting the compute unit price, we’ve shown how you can prioritize your transactions over others, which is especially useful for time-sensitive operations. This guide has equipped you with the knowledge to incorporate priority fees into your Solana-based applications, enhancing the user experience by reducing wait times for transaction confirmations.

Ake

Ake Director of Developer Experience @ Chainstack
Talk to me all things Web3
20 years in technology | 8+ years in Web3 full time years experience
Last modified on July 2, 2026