---
title: Program Derived Addresses (PDAs)
description:
  Solana Program Derived Addresses (PDAs) are deterministic, off-curve addresses
  derived from seeds and a program ID. No private key exists — only the deriving
  program can sign via invoke_signed.
url: /docs/core/pda
type: conceptual
prerequisites:
  - /docs/core/accounts
  - /docs/core/programs
related:
  - /docs/core/pda/pda-derivation
  - /docs/core/pda/pda-accounts
  - /docs/core/cpi
---

Program Derived Addresses (PDAs) are 32-byte account addresses that are
deterministically derived from a program ID and a set of seeds. They are
guaranteed to not lie on the Ed25519 curve, which means no private key exists
for them. Only the program whose ID was used in the derivation can "sign" for a
PDA, and it does so through [`invoke_signed`](/docs/core/cpi) during
cross-program invocations (CPIs).

![Program Derived Address](/assets/docs/core/pda/pda.svg)

<Cards>
  <Card title="PDA Derivation" href="/docs/core/pda/pda-derivation">
    Derivation algorithm, canonical bump, findProgramAddress examples with
    different seed types.
  </Card>
  <Card title="PDA Accounts" href="/docs/core/pda/pda-accounts">
    Creating accounts at PDA addresses, invoke_signed signing, Anchor patterns.
  </Card>
</Cards>

## Key facts

- **Deterministic**: The same seeds and program ID always produce the same
  address.
- **Off-curve**: The derived address is verified to not be a valid Ed25519
  public key. If the hash happens to land on the curve, the derivation fails and
  a different bump seed is tried.
- **No private key**: Because the address is off-curve, no one can produce a
  cryptographic signature for it. The program "signs" via the runtime's
  _rs`invoke_signed`_ mechanism instead.

## When to use PDAs

- **Deterministic addressing**: Derive the same account from the same seeds
  every time.
- **Program signing**: Only the owning program can sign via _rs`invoke_signed`_,
  enabling programs to act as autonomous authorities.
- **User-scoped state**: Derive per-user accounts from user pubkey seeds (e.g.,
  `["user", user_pubkey]`).
- **No keypair management**: No private key to store or lose. The address is
  derived purely from seeds.

## Limits

| Limit                                  | Value                            | Source                                                                                                                       |
| -------------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Max seeds                              | 16                               | [`MAX_SEEDS`](https://github.com/anza-xyz/solana-sdk/blob/clock%40v2.2.3/pubkey/src/lib.rs#L47)                              |
| Max seed length                        | 32 bytes maximum per seed        | [`MAX_SEED_LEN`](https://github.com/anza-xyz/solana-sdk/blob/clock%40v2.2.3/pubkey/src/lib.rs#L45)                           |
| Bump range                             | 0-255 (1 byte)                   | Appended as the final seed element                                                                                           |
| `create_program_address` cost          | 1,500 CUs                        | [`create_program_address_units`](https://github.com/anza-xyz/agave/blob/v3.1.8/program-runtime/src/execution_budget.rs#L200) |
| `find_program_address` worst-case cost | 1,500 entry + 1,500 x iterations | 1,500 on entry + 1,500 per failed bump                                                                                       |
| Max PDA signers per CPI                | 16                               | [`MAX_SIGNERS`](https://github.com/anza-xyz/agave/blob/v3.1.8/program-runtime/src/cpi.rs#L62)                                |
