> It will fail and be rolled back and you will lose the user's data that was written in it,
The point of relational integrity is ensuring all your data is in a valid state. If you don't want to lose a client's data because you deleted a city, there are multiple engineering approaches open to you.
1) Don't delete cities, just don't. The semantics of doing so don't make any sense in the first instance.
2) Further, deleting entities from an RDBMS is pretty damn final. What if a business analyst wanted to do some historical analysis? Well, that city is gone now, so it won't be there. This is where "soft delete" comes in (And no, soft delete doesn't destroy referential integrity) - you've marked the entity as no longer valid for use, but you still retain your data surrounding it.
3) Don't respond with a 2xx until the data store acknowledges successful insertion.
4) Use Debezium or similar to broadcast entity changes to a Kafka topic keyed on entity id. If you want to retain all changes (e.g., for event streaming), then use an appropriate retention strategy. If you want to retain only the latest state, use log compaction - it will retain the latest record with a given key.
This makes it easy for an app being spun up to obtain the entity state without touching the DB, and by continuing to subscribe to the topic, update its cache to match the source of truth.
Of course, you don't have to use Kafka, it's just one approach, but many other systems will allow you to do the same.
Basically, your objections say nothing about the usefulness of a relational datastore, but rather, the need for careful engineering when building overly distributed systems.
And through all this, I'm wondering how you imagine a non-relational datastore solving these problems any better.