01 / PRACTICAL NOTES
Saved is not the same as delivered
A message interface needs to distinguish the user’s intent from a network outcome. Saving a message locally means it can survive the application being interrupted. It does not mean another device has received it. SheraChat’s development architecture therefore treats the local working set and the server’s canonical history as different responsibilities.
02 / PRACTICAL NOTES
The outbox carries the intent
A durable outbox keeps the pending action available after a connection fails. The message is identified before a send attempt so a retry can refer to the same action. Otherwise an uncertain acknowledgement can lead to either a duplicate message or the loss of a message the user believed was saved. Persisting the intention first gives reconciliation something concrete to work with.
03 / PRACTICAL NOTES
Realtime events still need reconciliation
A live event stream can update the conversation quickly, but it should not be the only path back to a complete history. A client that was disconnected needs to compare its local state with the canonical records. The implementation must decide how a pending message, a returned record and a realtime event refer to one message rather than three separate entries.
04 / PRACTICAL NOTES
Make the states readable
Saved locally, queued, accepted and failed are distinct states with different next actions. An interface should help the person understand whether to wait, retry or investigate. Animation can connect an action to a visible result, but the state needs to remain understandable without motion or a perfect connection.
05 / PRACTICAL NOTES
The release boundary matters
SheraChat remains in development. Its Flutter, Supabase and Hive architecture demonstrates the approach described here, while production device, security and backend verification remain separate work. The verified implementation is not end-to-end encrypted. Reliability engineering should not be used to imply a security feature that has not been implemented.