TLDR: It depends.
TLDR++: Scale based on which service you are finding is the bottleneck. If you increase web apps, you might introduce a bottleneck at the database layer. If you add more shards, you might find the bottleneck is on the I/O disk layer. Always identify what you are using in your scenario, and then remove bottlenecks as they appear.
As you mentioned, the scenario you are scaling for will directly impact what approach you take.
In a production environment, you should operate your shard databases on a separate server from the other databases. This is probably the first scaling point you will do to ensure the database has enough power to handle the service communications.
If you are attempting to handle high visit traffic on the content delivery nodes, then your scaling point will be on the collection service part of xConnect to meet with the demands of the content delivery server when it reports the sessions. As you grow, you would vertically scale first by isolating search/collection from the other services so it runs as its own application, and then possibly load balance that xConnect services as you get into really high loads. See the KB article on 9.0 ARM templates (linked below) for some guidance on what architectures are suggested at different visitor counts.
However, if you are looking at an omnichannel integration you might scale out differently. You would have to look at how often you are calling the services, and which services you are hooking into, and vertically/horizontally scaling those services to be able to handle your non-CD load. xConnect collection/search are likely the first points again to isolate and then scale up and out. That being said, some integrations might be about filling up reference data lookup tables for use by other applications, so you might be scaling out that particular service because of your needs.
You also likely should look at putting in place a middle-layer application for your omnichannel implementation so that you are not having devices around the world directly communicating with xConnect. Not only are you handling a lot of chatty behaviour, you start introducing latency issues depending on connectivity of the device and location in the world. All devices would also need to be trusted clients with the correct certificate in order to communicate, so instead it may be worth having a layer that you manage which is a trusted application and receives and relays requests. This can be especially helpful to reduce chatty communications and act like the session-flush that the CDs execute. Gather up all the data from a user, and then flush it all out when the 'session' ends. This will reduce the back and forth with the xConnect services and allow for you to geo-distribute more efficiently.
In your scenario where you want to be updating contact info with data from some other system (or from the current visit) you are hitting the Collection service for the storing and the Search service for the getting. Depending on which one you are doing more of, you should scale appropriately. If you do a lot of updating, it's the Collection service you want to isolate and scale.