I think, your question is not specific to Akka.NET exclusively. So I'll answer it being Akka/Scala developer.
0 Not everything is an actor. Functions are still functions with all that functional composition and purity.
- Actor model becomes very useful when you extend beyond CRUD in the land of Domain-Driven-Design and Hexagonal Architecture.
- I can't tell for .NET, but in the JVM world most database calls (JDBC) are blocking. Meanwhile, actor system usually works on a limited thread pool compared in size to the number of your CPU cores. So, if your actor system works with blocking calls, Akka allows to configure separate thread pool for that subsystem, i.e. subtree of the actor system's supervision tree. So you can leave your nonblocking business core with 4 threads and give 200 threads to storage subsystem.
- Immutable (Persistent, Functional) data structures are the key. You don't need synchronisation to use them. Though sometimes you may need to pass a reference to e.g. ByteStream. Well, you should check that sender doesn't try to work with the instance after it had been sent.
In general, what is the main difference between Erlang and Akka implementations?
In Erlang each actor has its own heap and garbage collector. Hence, no shared mutable state, no stop-the-world gc. This gives us soft realtime qualities. But you pay on copying data from actor to actor. In JVM (and .NET?) heap and gc are shared. You don't have overhead like in Erlang, but you should be disciplined not to shoot yourself in your own foot.
Now a couple of use cases I myself have encountered.
You know RabbitMQ: exchanges, queues, bindings... If connection fails - some drivers can automatically redeclare them all. I've implemented this logic with Akka, because the driver didn't suit my needs. It was first hard to figure out that logic, but after a managed to separate, what was ephemeral, and what should persist failure - things clicked. The former went to worker actors, while the letter resided in actor's props (which is effectively an actor instance config) and supervisors. This is what is meant when you hear of actor resiliency and self-healing. It is not out-of-the-box, but actors help greatly to implement this logic as straightforward as possible, right after you figure it out yourself.
Hexagonal architecture and concurrency. I've implemented CAS 3.0 Protocol Specification for internal needs using Akka.
First of all, business core, http server, http client, db interaction - all were separated in different actor subsystems and had clear interaction surface. You can test them separately. Business core doesn't know, what an http protocol is. It just known how to handle business commands. It doesn't know anything about db including interfaces. It just knows what messages to send and what to receive. And db's ActorRef, of course.
Second, in CAS protocol there are quite a few things that you need to check for a single user request. So, I implemented every check in a separate worker actors. They are configured with necessary ActorRef-s and a timeout. Either they finish processing before timeout and commit suicide, or the timeout is reached, and the produce error response and, again, commit suicide. Meanwhile, there are other actors, which I called services. They act as supervisors for mentioned workers and existed as long as the whole runtime. Their ActorRef-s are static addresses, which you can use to configure different runtime components during application startup.
Hope this helps