Where the two comes from
The specification lays out exactly what gets encoded. Take the 32 byte public key, take a 1 byte version marker, and take the first 2 bytes of a hash computed over a fixed string plus the key plus the version. Concatenate the three in a defined order and encode the result. That is the whole address.
The two bytes are truncated from a full length hash, so they are not a cryptographic guarantee of anything. They are the digital equivalent of the extra digit on a credit card number. Sixteen bits gives 65,536 possible values, so a random corruption gets past the check about once in every 65,536 attempts.
address = base32( pubkey || checksum || version )
What sixteen bits buy you
They buy local rejection. Your client can tell that an address is malformed before it sends a single packet to anybody. Nothing on the network learns that you tried, and you get an immediate error rather than a timeout. That is a small privacy win and a large convenience one.
They also make copy and paste damage visible. Addresses lose characters when they pass through chat clients that treat them as words, through PDFs, through screenshots run under text recognition. All of that shows up as a hard failure rather than as a silent wrong destination.
What people get wrong about it
The word checksum makes people think of verification. It verifies that the string is internally consistent. It cannot verify that the string is the one you wanted, because anybody generating an address computes a valid checksum for it automatically. Every fake address in existence has a perfect checksum.
The second misreading is about size. Sixteen bits sounds like a lot in a subject full of small numbers, and it is nothing. A search that has to hit a specific 16 bit value finishes on a laptop before you notice. If the checksum were the thing standing between you and a forged address, forgery would be free.
What actually stands there is the 32 byte key, which is a different number entirely.
What would move it
Only a revision of the address format, and there is no sign of one. When the format last changed, the address grew from 16 characters to 56 and the checksum arrived. A future version would probably grow again rather than shrink.
One thing worth noting: the two byte figure is fixed, but the hash function used to compute it is part of the same specification, so a change there would also count as a format change and would produce a different address for the same key.
One more thing follows from the two being truncated rather than complete. There is no way to work backwards from a checksum to a key, and no way to use it to repair a damaged address. Software that offers to fix a broken onion address is guessing, and a guess that happens to produce a valid string is a guess that has produced somebody else's address.
Questions people ask
If the checksum passes, is the address real?
It is well formed. That is all. A well formed address can point anywhere, including at a copy of the market that exists to take your credentials.
Can I compute the checksum myself?
Yes, with any tool that implements the specification. It is not a useful check in practice, because a passing checksum tells you nothing about ownership.