...
/Design Considerations for Chat Application Mobile System
Design Considerations for Chat Application Mobile System
Understand the design considerations related to mobile architecture patterns and communication, and tackle mobile constraints for the chat application mobile System Design.
With the functional requirements and constraints laid out in the first lesson, it’s now time to confront the critical design considerations that shape how a mobile chat application behaves, scales, and adapts to real-world usage. Unlike a read-heavy experience like a newsfeed, chat applications demand real-time communication, precise state synchronization, and intuitive conversational flows. These demands require thoughtful decisions at every layer, from selection and UI responsiveness to how the system handles offline usage and background constraints.
This lesson focuses on the foundational decisions that will determine the robustness, responsiveness, and maintainability of your mobile chat system. We’ll revisit key architectural choices, such as the use of coordinators, dependency injection, and MVVM, to evaluate whether they still hold up in the context of chat and, if so, how they must evolve. We’ll also address communication architecture, message delivery mechanics, state synchronization, and interaction patterns like presence and typing indicators.
Before exploring chat-specific mechanics like message streams and real-time sync, it’s important to revisit foundational architectural decisions that can serve as the backbone of the entire application.
Let’s start with a mobile architecture pattern.
Architecture pattern
The choice of architectural patterns becomes critical to maintaining clarity, extensibility, and real-time responsiveness. Messaging workflows span multiple screens, background states, and asynchronous event streams. Without a disciplined structure, the system risks becoming brittle and difficult to reason about as it scales.
We adopt an MVVM-C (Model-View-ViewModel with coordinators) pattern coupled with dependency injection (DI) for a chat application. This pairing offers a powerful combination of modularity, separation of concerns, and flexibility across both UI and data layers.
Let’s understand the logic behind the decision.
MVVM (Model-View-ViewModel): In a chat application, message lists are updated in real time, sometimes multiple times per second. This includes new messages, status indicators, reactions, edits, and typing states. By isolating presentation logic in ViewModels, we ensure that UI components (Views) remain simple and declarative, focused purely on rendering the state exposed by the ViewModel. This not only avoids bloated view controllers, but also enables easier unit testing for scenarios like optimistic sends or failed deliveries.
Coordinators for navigation: Chat applications involve a surprisingly rich set of navigation flows: opening a thread from a push notification, launching media previews, transitioning to profile views, or returning to the inbox after archiving a conversation. Embedding this logic in view controllers leads to tangled code. Coordinators encapsulate these flows, allowing navigation to be declared explicitly and in a testable manner. They also help manage edge cases, like dismissing a media overlay when the underlying conversation is archived remotely.
Dependency injection (DI): Unlike stateless browsing features, chat sessions often involve persistent resources like WebSocket clients, media uploader, or encryption layers that should exist only during the lifetime of a conversation. Using DI containers allows us to:
Construct per-session service graphs dynamically.
Easily swap or mock dependencies (e.g., during testing or A/B experiments).
Isolate failure domains: a bug in media uploading doesn’t compromise core messaging.
This approach also improves memory efficiency and life cycle management, since unused services are deallocated once the conversation ends.
As the application grows, new engineers or new features like polls or replies can be onboarded into the architecture without requiring deep rewrites. A well-structured MVVM-C + DI setup reduces ramp-up time by making responsibilities discoverable, components independently testable, and behaviors more predictable.
Our chat screen uses optimistic UI to show messages immediately after hitting send. Where should the message state (sending, sent, failed) be managed: the ViewModel or a sync service?