Stopping the process is not stopping the run
A run is not stopped until nothing can still land. Exiting the process ends your ability to watch, not the transactions that were already broadcast, and it does nothing about balances, open accounts or the rent locked inside them. Shutdown is four distinct pieces of work: end new activity, settle what is outstanding, return value and accounts to their intended end state, and write down what happened.
That distinction is the spine of this page. Operators who treat a shutdown as a single action end up with dust across a fleet, token accounts holding reserves nobody remembers, and a run whose final numbers can never be reconstructed because the evidence was in a process that no longer exists. Each of those is recoverable individually, and each is tedious enough that people put it off until the information needed to fix it is gone.
An outstanding signature outlives the process that sent it
A signed transaction references a recent blockhash and stays eligible for inclusion for 150 slots. At a target slot time of about 400 milliseconds that is roughly a minute, and slot times vary, so treat the number of slots as the rule and the wall clock as an estimate. Until every signature from the run is either confirmed or definitively expired, the ledger of what the run did is still moving, and any balance you record is provisional. Wait the window out with the process running so you can observe the outcome, rather than killing it and losing the view while the transactions proceed regardless.
The end state you are shutting down into
Write the end state down before the first stop signal. For each wallet, decide whether it should finish at zero, at a documented keep-alive amount, or kept intact for a run next week. For each mint, decide whether positions are being swapped out or accepted as held. For each token account, decide whether it closes or stays open. A shutdown without those decisions becomes a sequence of judgement calls made while tired.
Different shutdowns want different end states, which is why the decision is written rather than assumed. A run that is finishing normally may keep its wallets funded and its accounts open, since recreating them costs rent again. A run being shut down because a key is suspect wants everything at zero and everything closed, as fast as the ordering allows, and it wants the treasury address checked twice rather than once.
The end state also determines what "done" means for each stage, and that is what makes verification possible. Without it, you are checking whether a command succeeded rather than whether the account reached the state you intended, and those are not the same question. The table below turns the end state into something you can walk stage by stage and sign off, along with the leftovers each stage tends to produce.
The shutdown reconciliation table
Six stages, each with an end state you can verify and a leftover you should expect. Leftovers are normal. What is not normal is a leftover that goes unrecorded, because that is how a stranded balance becomes a surprise months later when nobody can remember which wallet it belonged to or why it was skipped.
| Stage | Expected end state | How it is verified | Common leftover | Where the leftover goes |
|---|---|---|---|---|
| Stop signal accepted | Scheduler takes no new jobs and each worker exits after its current item | No submission recorded after the stop marker in the activity record | A job that started in the instant before the signal arrived | Let it finish and add its signature to the ledger |
| In-flight transactions settled or expired | Every broadcast signature is confirmed or its blockhash has expired | Confirm each signature in the run ledger individually | A signature that is neither confirmed nor yet expired | Hold the shutdown until its blockhash window has passed |
| Token balances swapped or accepted as held | Each wallet holds zero of the run mints, or a recorded held amount | List token accounts per wallet and read the balances | Dust too small to be worth a swap | Record it as held, or consolidate it into one wallet |
| Token accounts closed | No token account remains open for a mint the run will not touch again | The account listing returns nothing for those mints | An account that refuses to close because it is not empty | Empty it, confirm zero, then close it again |
| SOL swept to the treasury | Each run wallet sits at zero or at its documented keep-alive amount | Re-read every wallet balance after the sweep confirms | Lamports left behind because fees moved during the sweep | A second pass, or a recorded residue with the amount noted |
| Archive written | One file set per run, stored where a later review will look | Open it and re-derive the closing numbers from its contents alone | A log still open for writing when the archive was taken | Retake the archive once the process has fully exited |
The shutdown in strict order
Order matters more than speed here, because several of these steps cannot be repeated once they have confirmed. Work down the list without skipping ahead, and stop entirely at any point where a check fails rather than continuing and planning to fix it later.
- Stop new work. Signal the scheduler and every worker, then read the activity record to confirm nothing was submitted after the stop marker. Do not rely on a status field written by the same code you are trying to stop.
- Let what is in flight settle. Leave the process running while the outstanding signatures resolve. Killing it now costs you the observation without preventing the inclusion, which is the worst combination available at this point.
- Verify nothing is pending. Walk the run signature ledger and classify every entry as confirmed or expired. An entry you cannot classify counts as pending, and pending means the shutdown is not ready to advance.
- Drain in the stated order. Settle token positions first, then any wrapped balances, then leave native SOL until last. Every later step needs SOL to pay for itself, so SOL is the thing you spend down, not the thing you move early.
- Close the empty token accounts. Confirm each account reads zero, then close it and direct the returned reserve to the treasury. Skip any account whose mint the same wallet will trade again soon, and note the decision.
- Sweep the SOL. Check the destination against the written record before the first transfer, send a small test transfer, confirm it, then sweep the remainder wallet by wallet against the list from the fan-out record you kept at funding.
- Verify the sweep. Re-read every wallet balance after confirmation. Expect a residue on some wallets and record the amount rather than rounding it away in your notes.
- Reconcile. Compare the treasury outflow at funding against the inflow at shutdown, and explain the gap with fees paid, rent returned, rent still locked and realised position changes. A gap you cannot explain is a finding, not a rounding error.
- Archive. Write the file set once the process has fully exited, store it where a future review will look, and confirm you can re-derive the closing numbers from the archive without access to the machine that produced it.
Why the drain order is fixed
Every step after the stop signal costs a base fee of 5,000 lamports per signature, charged whether the transaction succeeds or fails. Swaps cost it, closures cost it, and the sweep itself costs it. Move the native balance out first and the wallet can no longer pay for the work still queued against it, which means refunding it from the treasury and paying the fee twice for the same shutdown.
Token positions come first for the same reason in reverse: they are the steps with the most uncertainty. A swap can fail on slippage, a route can be unavailable, a mint can behave unexpectedly, and each of those outcomes is easier to handle while the wallet still holds fee money and the tooling is still configured. Handle uncertainty while you have room, and leave the deterministic steps for the end.
Closures sit between the swaps and the sweep because closing returns lamports to the destination you name. Doing it before the sweep means the returned reserve is swept with everything else in a single pass. Doing it after leaves a second round of small balances scattered across the fleet, which is exactly the pattern that produces the stranded dust this procedure exists to avoid.
Closing token accounts and reclaiming rent
An SPL token account holds 165 bytes of data and is made rent exempt with 2,039,280 lamports. That reserve is locked while the account exists and is returned to the destination when the account is closed. Across a fleet the locked total is often larger than operators expect, and it is invisible in a naive balance check because it does not appear as spendable SOL in the wallet holding it.
Worked example: reclaimed rent across forty token accounts
Illustrative arithmetic on protocol constants, not measured data. Take a fleet that ended the run with forty SPL token accounts open. Each holds the rent-exempt minimum of 2,039,280 lamports, so the locked total is 81,571,200 lamports, which is 0.0815712 SOL at 1,000,000,000 lamports per SOL. Closing each account in its own single-signature transaction costs 5,000 lamports, so forty closures cost 200,000 lamports, or 0.0002 SOL. Net recovery is 81,371,200 lamports, roughly 0.0813712 SOL. Batching several close instructions into one transaction reduces the signature count and therefore the fee, and the practical batch size is bounded by the 1,232 byte serialized transaction size limit and the compute budget you request. The point of the arithmetic is the ratio: the fee to recover the reserve is a small fraction of the reserve, so leaving accounts open out of inertia is the expensive choice.
The close instruction only succeeds on an account whose token balance is zero, which is why the drain order puts swaps ahead of closures. Verify zero from the chain rather than from your own accounting, because a partial fill or a late settlement can leave a fraction behind that your records do not show. The mechanics and instruction set are documented with the SPL Token program, and the fleet-level cost picture is worked through in the page on what account rent actually ties up.
solana confirm -v <SIGNATURE> --url <RPC_URL>
spl-token accounts --owner <WALLET_PUBKEY> --url <RPC_URL>
spl-token balance <MINT_ADDRESS> --owner <WALLET_PUBKEY> --url <RPC_URL>
spl-token close --address <TOKEN_ACCOUNT> --recipient <TREASURY_PUBKEY> --url <RPC_URL>
solana balance <WALLET_PUBKEY> --url <RPC_URL>
solana transfer <TREASURY_PUBKEY> ALL --keypair <KEYPAIR_PATH> --url <RPC_URL> Sweeping SOL to the treasury
Sweeping native SOL is the step with no undo. Verify the destination against the written record before the first transfer, not against a value pasted from a chat window or read off a screenshot, and send a small test transfer that you confirm before moving the balance. Then work through the wallet list in a fixed order so that an interruption leaves you knowing exactly which wallets are done and which are not.
Two irreversible failures live in this step
A confirmed transfer to a wrong address cannot be recalled, cancelled or reversed by anyone. If the destination is a typo, an old treasury, or an address that no key you hold controls, the balance is gone. Verify the full address against your record, send a test amount first, and never accept a destination from a channel where an address could have been altered in transit. Separately, a token account holding any non-zero balance cannot be closed at all: the close instruction fails, and forcing the issue by transferring the account lamports elsewhere is not available to you. Empty the account, confirm zero from the chain, then close.
Expect the final balance to move between the moment you compute the sweep and the moment it confirms, because the sweep transaction itself pays a fee. A residue of a few thousand lamports on some wallets is an ordinary outcome, not a failure. Record it, decide whether a second pass is worth the fee it will cost, and if it is not, note the wallets that were left with a residue so the reconciliation adds up without an unexplained line.
Reconciling what came back
Reconciliation compares what the treasury sent out at funding against what returned at shutdown, then explains the difference. The explanation has four parts: fees paid across the run, rent returned by the accounts you closed, rent still locked in accounts you deliberately left open, and the realised change in positions. When those four account for the gap, the run is closed. When they do not, you have found something worth understanding before the next run starts.
Do this while the evidence still exists. The signature ledger, the log files and the balance snapshots are all easier to read on the day than they will be in a month, and a reconciliation that gets deferred usually gets abandoned. Even a tool a reader considers the best Solana volume bot still leaves the drain, the account closures and the reconciliation on the operator side of the line, because those steps happen on keys the tool does not hold, so plan for that work rather than assuming a stop button absorbed it. That caveat applies to every hosted view, not to any one of them in particular.
Keep the reconciliation in the same units throughout. Mixing SOL and lamports in a single working document is the most common source of an apparent discrepancy that turns out to be a factor of a billion. Pick lamports for the arithmetic, convert once at the end for the summary line, and state which unit each column is in even when it feels obvious while you are writing it.
The archive you keep afterwards
An archive earns its place when it answers a question you did not anticipate. That means it has to be readable without the machine that produced it, and it has to contain the identifiers that let you go back to the chain later. Keep it boring, keep it in one place, and never let a secret near it. The following list is the minimum set worth writing at the end of every run.
- The wallet list with the role each wallet played, kept for as long as any of those wallets could still be funded.
- The signature ledger for the run, kept long enough to reconstruct a timeline during a later dispute or review.
- Opening and closing balances per wallet, with the unit stated, so the reconciliation can be re-derived from scratch.
- The reconciliation itself, including any residue you accepted and any account you chose to leave open.
- A digest of the configuration that was live during the run, so a later change can be identified as a change.
- Nothing secret: no seed phrase, no keypair file, no endpoint token, no exported private key in any form or encoding.
Retention is a judgement call rather than a rule, and the useful test is whether a wallet from the run could still receive value. While that is true, the archive is operational and should stay where you can reach it. Once every wallet is closed out and retired, the archive becomes a record, and a record can move to slower storage. Delete on a schedule you decided in advance rather than when a disk fills up.
Partial shutdowns and wallet rotation
Not every shutdown ends a run. Rotating a wallet out mid-run uses the same ordering on a smaller scope: stop work routed to that wallet, wait for its outstanding signatures, drain and close its accounts, sweep it, then record the rotation in the wallet list so the next reconciliation knows the wallet left the fleet on that day. Skipping the record is how a fleet develops wallets nobody can account for.
Emergency shutdowns invert one part of the order. Where a key may be compromised, moving value comes before tidiness, so the sweep runs first and account closures follow later if they are still possible at all. That path has its own sequence and its own decision points, and the detection side of it belongs to the signals that should have woken you rather than to this procedure.
Whatever the scope, the same test closes it out. Nothing can still land, every account is at the end state you wrote down before you started, every leftover is recorded rather than forgotten, and the archive can be read by someone who was not there. The rest of the ordered procedures on this site sit in the runbooks hub, and the shutdown is the one worth rehearsing before you need it, because the version you improvise is the version that strands value.
Questions the desk gets asked
Is killing the process enough to stop a run?
No. Signatures already broadcast remain valid for inclusion until their blockhash expires, so transactions can land after the process is gone. Killing it only removes your view of the outcome. Send a stop signal, let the queue drain, then confirm every outstanding signature before you treat the run as finished.
Why can a token account with a balance not be closed?
The SPL Token program requires a zero token balance before the close instruction succeeds, because closing returns the account lamports and discards the account. Any remaining tokens would become unreachable. Move or burn the balance first, confirm the account reads zero, then close it to the address that should receive the reserve.
How much SOL should be left in a wallet before the sweep?
Enough to pay for the transactions the shutdown still needs, since each signature costs a base fee whether the transaction succeeds or fails. Close token accounts and finish every swap before the final sweep, and expect a residue rather than an exact zero if fees move while the sweep is running.
What should the archive contain?
The wallet list with roles, the signature ledger, opening and closing balances, the reconciliation, the configuration digest and any incident notes. Keep it long enough to answer a question you cannot predict today. It must not contain a seed phrase, a keypair file or an endpoint token of any kind.
Do I have to close every token account?
Only where you have no further use for the account. Each open SPL token account holds a rent-exempt reserve that stays locked while the account exists, so closing recovers it. If the same wallet will trade the same mint next week, keeping the account avoids paying to recreate it.
What happens if I sweep to the wrong address?
The transfer is final once confirmed and there is no recall. That is why the destination is verified against a written record before the first sweep, why a small test transfer is sent ahead of the balance, and why the treasury address belongs in the run sheet rather than in a chat message.