There are many tradeoffs here. Actually I use string keys frequently, but often I include surrogate secondary keys for joins (obviously it would be the other way around if I was using MySQL). There are cases where I don't however.
First I am a fan of declaring natural keys as the primary key where the db can handle this well (PostgreSQL for example). This helps with normalization and makes for clearer database design. Surrogate keys make joining easier.
There are two reasons I usually add surrogate keys:
It isn't always clear what a natural key is. Sometimes these have to be changed. Changing a natural, composite key when it is used for joins and referential integrity is complicated and error prone.
Join performance on composite keys is problematic and once you go down the natural key route, you get stuck there.
In cases where a natural key is definitional, single column, and text, however, I usually join on the string key. My reason for doing so is that this often avoids joins on lookup. The most common use is providing proper db design around the use case of enum types. In most cases, these do not require the extra join for routine queries. So where this is the case, string keys as join keys makes perfect sense.
For example in LedgerSMB, we store account categorizations. These are identifed by string reference.and some other data is stored with the string reference which is used to enforce rules regarding the combinations of categorizations that can affect an account. The only time that logic is needed is when saving a set of categorizations, so we join on the string key.
As to why the default would be integer keys, I don't think it's just a question of index size. A big issue is management of keys. Since the key is arbitrary and you may be dealing with millions of records, you have to have a way of generating unique strings. There are cases where people use UUIDs for this, but there is a non-zero chance of UUID collision, and where billions of records are stored, this chance becomes high enough one might actually see while the chance of collision with incremented integer types is zero by definition.
username
as the primary key of ausers
table is probably not the best idea, and you'd prefer an auto-increment id. But thatusername
is a string is only incidental, being a mutable property is the main issue