Design the synchronization boundary

A small team building an email app has limited attention. Every hour spent coordinating network conversations is an hour unavailable for explaining a failed import or making a message readable. JMAP is interesting from that perspective: it offers a more coherent boundary between the client’s local model and the service holding the mailbox. The benefit is architectural clarity, not a promise that email becomes effortless.

The foundation is RFC 8620, published in 2019. RFC 8621, also published in 2019, defines JMAP for Mail, including email objects, mailboxes, threads and submission. It is an open standard with a defined data model, rather than a proprietary endpoint a client must reverse-engineer.

Describe the work instead of choreographing requests

JMAP exchanges JSON over HTTPS. A request can contain multiple method calls, and a later call can reference a previous call’s result. For an inbox view, that means a client can describe a query and the data it needs from the resulting identifiers together, within the server’s advertised limits. Fewer dependent network turns can matter on a connection with high latency, although actual results depend on the workload and implementation.

For builders, the attractive part is making dependencies explicit. The code can express which properties a screen needs and which results feed the next operation. It still needs pagination, error handling and limits on work. Batching is a tool for organizing requests; it is not permission to fetch an entire account whenever a window opens.

Treat state as a durable checkpoint

State tokens let the client ask what changed since a known point. The /changes methods report created, updated and destroyed identifiers; the app can retrieve the data it needs and update its local store. Push notifications signal state changes so the client knows when to synchronize. They are prompts to reconcile, not a substitute for reconciliation itself.

A checkpoint is only useful if it describes data that really reached durable storage. An app must plan for a crash between receiving a response and saving it. It must also handle cannotCalculateChanges: if the server cannot supply the requested history, a fuller resynchronization is required. Recovery is part of the normal design, including after a long absence, not an exceptional feature to add after launch.

Keep the remaining responsibilities visible

JMAP does not replace SMTP delivery between mail servers. Mail submission through JMAP is a client-facing operation; the wider mail network continues to need delivery infrastructure. Nor does selecting JMAP automatically remove spam, provide end-to-end privacy or make an application work offline. Offline behavior still requires local storage, a policy for queued actions and a way to handle conflicting changes.

Support is not universal. A product must discover capabilities, decide which providers it supports and keep compatibility paths where appropriate. Performance depends on the server, client and workload. Modern IMAP also has synchronization capabilities, so the comparison deserves more care than “old versus new.”

The studio lesson is to choose a contract that makes recovery understandable. Our history of email’s implementation complexity explains the inherited constraints. MailVault’s guide to how JMAP modernizes email follows the user perspective. Clearer server communication creates room for a better app, but the team must still build it.