Pretty much agreed. Two things to add:
> Simpler means conceptually independent things aren't coupled together. For example, ORMs couple together object-oriented code and relational objects. That's the essential complexity that they introduce.
I don't actually agree that this is where the complexity comes from. The complexity comes from what makes ORM so appealing in the first place. Your ORM can dynamically generate an infinite variety of queries based on how you use it, which makes it a big piece of machinery with many moving parts, the behavior of which you will have to understand and manage even if you didn't build it yourself. This machinery may break, it may behave in undesired or unpredicted ways, it may consume compute resources inefficiently, and if it does any of those things, you're still on the hook to take care of it because it affects the behavior of your product.
Ultimately, you will always have to map some behavior in your service code to an intended SQL query and then map the result set back to in-memory data. Doing so in a consistent way can potentially reduce complexity, though in a lot of cases, you can probably get away with treating a SQL result set as a list of associative arrays, or even a list of objects as long as you tell it what class to deserialize into (which is what many ORMs do anyway).
> There's still the old-fashioned way of checking them into the repo as part of migrations.
Yes, even many ORM-based services have DB migrations in the service repo already.[1]
You could also version-control the stored procedures, database migrations, etc. as its own software artifact. You can think of a relational database as a service (microservice?) that speaks SQL instead of HTTP or GraphQL or GRPC. It's listening to a port somewhere on your network, it consumes computational resources, it will be deployed independently of your service in such a way that you have to worry about backwards compatibility, it can become unavailable to your service, and so forth. And like most services, you may prefer to have a defined, optimized, versioned interface to your DB instead of just trusting your consuming services to execute arbitrary (SQL) code. This is not necessarily the right or wrong solution for you, but it's reasonable enough.
[1] One possible niche might be an ORM that builds all of your DB manipulation commands into parameterized SQL at compile time and installs those SQL statements as stored procedures via the migration mechanism. Then you really can write raw SQL when you need to, by hardcoding your stored procedure instead of compiling it. This would work best on a DB that you could migrate whenever you felt like it, but I've heard Postgres is one of those.