Можно выделить несколько вариантов, у каждого есть плюсы\минусы, потому выбор оптимального зависит от конкретной задачи. Первые 2 варианта согласуются с озвученными в вопросе, но не исключаю и 4 вариант.
- Модуль списка контактов на клиенте зависит от 3-х сервисов (список контактов, сообщения, анкеты) - проблема в появлении дополнительных зависимостей в клиентском коде, что порой не так просто исправить\обновить и требует согласования контрактов указанных сервисов с клиентским кодом.
- Добавление в список контактов кэширующих-полей для соответствующих данных - в данном случае добавляется задача по выработке правил обновления данных в этих полях и их источнику при обновлении. В дополнение может добавиться "лишняя" ответственность к клиенту и\или сервису.
- Сервис составного списка контактов, который зависит от сервисов: список контактов, сообщений и анкет - имеем дополнительные зависимости, которые позволяют переместить ответственность по агрегации данных в отдельный сервис и дольше сохранять контракт взаимодействия с клиентами (в данном случае могут использоваться кэширующие-поля как в п.2). К тому же, если со стороны бизнес требований есть "список контактов", то логично, чтобы сервис возвращал весь набор требуемых данных, т.к. способ реализации этой задачи не должен интересовать клиентов сервиса. Но в данном случае предстоит решить задачу недоступности одного из сервисов в процессе обработки запроса (неплохо работает кэширование).
- сервис API-шлюз под каждый вид клиента - почти полностью аналогично п.3, с тем отличием, что данный сервис выступает точкой входа для доступа к методам\данным скрывая особенности реализации backend.
PS: Дополнительные уровни косвенности часто используются для повышения тестируемости, но и оно имеет свою цену.