Lots of conversations with people about Citus lately. Citus is a fascinating and advanced piece of technology, but not a one size fits all. If you're considering Citus here's the things to keep in mind.
Disclaimer-this is assuming a multi-tenant workload.
If you ever think you're going to need Citus, it's a good idea to slightly denormalize and have your tenant/customer id as a column on every table. The key is you don't want to have to join another table to get to the tenant_id/customer_id you want it there denormalized on every table.
Your primary keys will then become composite primary keys, composed of customer id the id for that table.
For joins you'll want to make sure you also include that tenant_id as part of joins for every coloumn, not just one table, for every single table in your query you want to make sure customer/tenant id is joined.
A good thing to check for before going to production is tweak the log setting for queries that are cross shard to error. Citus has a setting for this: ALTER DATABASE postgres SET citus.multi_task_query_log_level = 'error';
The other piece is determining your node size and cluster size ahead of time, don't prematurely plan for too large of scale.
A fun interesting learning, just doing the above with customer id and joins we saw customers that were planning to migrate to Citus saw a significant performance improvement from that alone.
As for shard sizing don't stress too much on it. Determine your starting number of nodes and then create a shard count that allows you to scale to 4x that. Don't start on the smallest instance size you can find, but don't start on the largst either. With all this a goldilocks zone middle of the road for all is the way you want to go.
Once you're live watch for hot spots on shards on particular tenants, and consider rebalancing or isolating those tenants. Citus expansion of pg_stat_statements (citus_stat_statements) will show you hot spots on tenants, and then you can isolate that tenant: SELECT isolate_tenant_to_new_shard('table_name', tenant_id);
And if you want to move that large tenant to their own dedicated node: SELECT master_move_shard_placement(shard_id, source_node_name, source_node_port, target_node_name, target_node_port)