What is the difference between minimal and upgradeable proxies?

Proxy contracts

A proxy is a simple contract that just delegates all calls to an implementation/logic contract. A delegate call is similar to a regular call, except that all code is executed in the context of the caller, not of the callee. Because of this, a transfer in the implementation contract’s code will actually transfer the proxy’s balance, and any reads or writes to the contract storage will read or write from the proxy’s own storage.

The proxy holds the state, while the implementation/logic contract provides the code.

Proxy contracts can’t use constructors and need to use Initialization.

Minimal Proxies

Minimal proxies (EIP 1167) are exactly that, minimal and cannot be upgraded.

They can be used to cheaply deploy a large number of the same contract, by deploying a single implementation/logic contract and a large number of minimal proxies.

For more details see:

Upgradeable contracts

Upgradeable contracts are proxies that can be upgraded. To upgrade a contract we deploy a new implementation contract and update the proxy to point to our new implementation contract.

For more details see:
https://docs.openzeppelin.com/learn/upgrading-smart-contracts#how-upgrades-work