> your stored data always has a schema, unless your code neither reads nor writes it as anything except an opaque blob.

This is well-put. I'd go further: if there's no schema, you don't have data at all. A row with labelled email and name fields is data; a string of free-form input in which the user describe him/herself is not data. You might possibly be able to extract data from it, but if you do, you'll be building a set of labelled fields.

> You can tell that your code's implicit schema exists even with an SQL database, even if your code auto-reads the SQL schemas, by asking what happens if the DBAs decide to rename a bunch of tables and a bunch of fields in those tables, maybe dropping some and adding others

Maybe a quibble, but I'd say your code has partial knowledge of the relational db's schema, not that it duplicates the schema, just as it may have knowledge of the file system structure, the domain names of various servers, etc, and depend on that knowledge being accurate, without duplicating them entirely.

> In some ways NoSQL is more honest than SQL, because it tells you straight up that it's entirely up to your code to have and maintain a schema.

With a relational db it's not entirely up to your code to have and maintain a schema. Eg, your code can assume that every "user" record has an "email" field and that it's NOT NULL and always a string and always unique, assuming the db is set up to guarantee that. The part of your code that reads records can be sure of that, even if the part of your code that writes records is lax about checking (and therefore blows up a lot). With a NoSQL database, it's possible that some records have blank emails, or numeric emails, or don't have that field at all, or have that field named something different. Those things will happen unless you're very careful to ensure in your code that they don't, and also unless you're careful to never to let anything write to the database except your code.

I think a differentiating question is "what is it that guarantees all your records of type X have the same schema?" If you use a SQL database, the answer can be "the db". With NoSQL it might be "a combination of app logic, background jobs and manual intervention for weird cases" or "nothing".

In cases where you want to store JSON blobs, an RDBMS like PostgreSQL lets you have a JSON column. This is useful (eg) for cases where you need to capture some input now, and might get around to parsing it out into real data later - eg "we got these records from the legacy system and don't yet know if / whether we can import them".

Finally, although I wouldn't advocate moving complex application logic to the database, there are some validations that can only be reliably done by the database itself or by leaning on the database. Specifically, any validation that relies on the current contents of the database, such as "don't allow duplicate user names" (unique constraint) or "don't allow creating a comment for a post that was deleted" (foreign keys) or "don't allow overlapping reservations" (PostgreSQL exclusion constraint). Application code can do a read, check, and insert, but two threads may have a race condition and insert conflicting data. Application code can ask the db to lock while it does this, but that's leaning on the db. Or the database schema itself can guarantee this in a safe and performant way. But only if the database has a real schema.