Adding this answer as a follow up to the comment
Yes, you’ve got it mostly right. Once a Program Data account (which holds the bytecode of the deployed program) is created, its size is immutable. This is enforced because program data accounts are managed by the Upgradeable Loader, which ensures security, consistency, and stability when upgrading programs.
When you upgrade a program, even if the new bytecode is the same size or smaller than the previous one, a new Program Data account must be created to hold the new bytecode. This is because the Upgradeable Loader doesn’t support in place updates for the program data. Instead, it maintains a controlled upgrade path by creating a fresh Program Data account with the new contents and then updating the Program account to reference the new one.
Even if the new bytecode is the same size or smaller, immutability is maintained to avoid potential issues such as leftover bytecode from the previous version, security concerns, or inconsistencies that could arise from in place modifications. Therefore, a new account is created to ensure a clean slate for the new bytecode.
On the other hand, regular data accounts, such as Associated Token Accounts (ATAs), Program Derived Accounts (PDAs), and any other accounts holding state for your application, can be resized in place using the realloc function provided by Solana.
ATAs (Associated Token Accounts): These are token specific accounts that hold balances of SPL tokens. They can be resized if needed, although in practice, they usually have fixed data layouts (e.g., a token balance and metadata), so resizing isn’t commonly required.
PDAs (Program Derived Accounts): These are typically used to store custom data related to your program and can be dynamically resized depending on your program's needs. For example, you might start with a PDA that holds a small amount of data and later need to expand its size to store more information. In such cases, you can use realloc to resize the account in place without needing to create a new one.
Realloc Process: The realloc
function adjusts the size of the account's data. When resizing upwards, you'll need to make sure that the account has enough SOL to cover rent for the increased size. When shrinking, excess lamports may be returned to the account's owner.