While with Let’s encrypt offering certificates free of charge and easily today does take away the “it doesn’t cost anything” argument, there are still reasons why self-signed certificates can be useful, for example
- for testing purposes (no CA is giving you a certificate for your local domain like testing.testenv.cooperation)
- on local networks (to secure routers’ web interfaces, for example.),
- as client certificates,
- for S/MIME,
- countering the problems of CAs in general.
The only real difference is that a CA-signed certificate is (usually) trusted without prompting the user for input while a self-signed certificate does need the user to validate it and put trust to it - for example by checking the fingerprint through a trusted channel. Once trust has been put into the self-signed certificate, it is as good as a CA-signed one (not counting rollover issues).
Self-signed certificates might come in handy when someone is not trusting the CA to not create a certificate for a MITM, for example.
Another big application of self-signed certificates (or more generally “non-CA-signed certificates”) can be client certificates: A web application can create certificates for authenticated users and use them to authenticate them from that point forward - certificate-based authentication is way better in terms of security than traditional username/password schemes and gets used often for B2B applications as well as mobile applications.
Using self-signed S/MIME certificates makes S/MIME about as convenient as GPG with the need to validate certificates manually (see above), but there are edge cases where someone without trust in a CA might have access to S/MIME encryption but not GPG (iPhone users, for example, as well as some corporate email clients)