Some technical proposals that were considered for the ethereum protocol but never made it in: a history
There have been a lot of protocol changes that have been suggested for Ethereum. Some were implemented quickly, others were implemented after many refinements, and still others were forgotten because of disinterest or because they proved to create more problems than they solve. Some of these ideas may be best left for dead, but others, after improvements, perhaps could make it in after all (though after high-priority stuff like merge, statelessness and EIP 1559). Here's a few examples of ideas that were once considered and are now ignored.
In the earlier stages of Ethereum's development (pre-launch), there was an opcode that was proposed called POST. A POST is equivalent to a CALL, except instead of the call happening immediately, the call happens at the end of thee transaction. It was abandoned because of pressure to launch on time and because there was not enough obvious value for it. Later on in 2016-18, there were serious discussions about revamping the VM in the context of sharding, and one of the ideas on the table was to make all calls asynchronous. This too was abandoned, as the sharding design moved to a maximally-simple MVP: just make many copies of the existing EVM and give them a simple (by necessity asynchronous) channel to talk to each other, but allow synchronous execution within shards. Demand for "defi composability" further closed the door on this, and Ethereum moving to an all-asynchronous model now seems very unlikely.
Transparent sharding with automated load balancing
Transparent sharding is a form of sharding where contracts would not even be able to tell which shard they are on, and contracts could be moved between shards by the protocol. The protocol would automatically move contracts between shards to ensure that the load on each shard remains about the same. This was also abandoned in response to remands for sharding to be simplified so that it could ship faster; additionally, it was never clear why this kind of sharding is better than "economic load balancing", where contracts themselves could hop between shards if they choose to, and users would naturally migrate to shards with lower gas costs and thereby help balance out the load.
In early 2015, an opcode called ALARM was also proposed. This opcode would also do a call, except the call would execute in some future block. This has many use cases; for example, withdrawals from rollups could finalize automatically, users who put their funds into bids at auctions could get their funds back when the time expires, etc. There are also applications for censorship resistance: a user could publish a transaction with an ALARM call, where the effect of the transaction depended on some other behavior that the user knew would happen between transaction sending time and alarm execution time, and block producers would not be able to censor it, MEV bots would not be able to manipulate it, etc.
This proposal was shelved out of pressure to launch faster, and we later learned that there actually is a lot of unforeseen technical complexity in making this work well. Particularly, imagine that all blocks
[N ... N + 99999] make an ALARM call that triggers in block
N + 100000. This would cause a huge spike in gas usage in that block. Solving this problem seems to require some notion of being able to pre-purchase gas of a future block, where the supply that can be pre-purchased is limited, but in principle it can be done.
SSTORE arbitrary-sized objects into one slot
This proposal was made with the goal of increasing efficiency and code simplicity, allowing users to save longer objects (strings, code…) into single storage slots, without the contract having to do a loop to split it up in many storage slots and without the Ethereum blockchain having to do all the extra hashing work of including many storage slots instead of one. The proposal was abandoned because it turns out that the complexity of figuring out gas costs for such a scheme is high, there may be database issues, and generally it adds very significant protocol complexity. Recent ideas are trying to go in the opposite direction, turning the one type of long contiguous storage that we do have (code) into a tree!
EIP 648 tried to add support for parallelizable execution, where transactions could specify which portions of the state they touch, and if two transactions touched disjoint parts of the state they could be processed in parallel. If we assume that Ethereum clients are multithreaded (most modern computers are), then this could significantly increase scalability. The proposal was shelved in part because it turns out that VM execution is not even the biggest bottleneck in limiting the safe amount of gas in a block (disk accesses and state size are), and even if we implemented it, Ethereum nodes would still become heavier and more difficult to run. However, the proposal is theoretically completely viable, and optimistic rollup projects are considering implementing it for the more high-performance-oriented EVM environments within their rollups!