Developers

Insight

How Messages writes its database

Messages is reported to keep iMessage, SMS, and RCS in one SQLite database. This page restates the shape and the version changes two public notes describe.

Published 10/19/2026  ·  3 min read

DEVI Ops Team

Messages needs one history that can include a text, a photo, a reaction, and a fallback from iMessage to SMS. The public notes describe that history as one SQLite database, not as three. Where the file sits, and what each column means for a case, is the other view of this topic.

What the database is for

The 09/25/2026 MessagingForensics note says Apple's Messages app keeps iMessage, SMS, and RCS in that database. On an iPhone the file is sms.db. On a Mac it is chat.db, and the note says the schema is the same one. The Mac copy can include conversations that started on a phone signed into the same account when Messages in iCloud is on. The note treats that as an attribution problem, not as a second schema.

The structure

message, handle, chat, and the join tables are the core the note names. is_from_me is the direction flag. service is the transport string (iMessage, SMS, or RCS on the versions the note calls recent). guid is the stable id. A reaction is another message row whose associated_message_guid points at the target and whose associated_message_type is in the 2000 or 3000 range. The note's table maps 2000 through 2005 to six tapbacks and 3000 through 3005 to removing them, and it says later codes exist.

text and attributedBody are two places for the body. The note says that from macOS Ventura, and the matching iOS versions, many rows leave text null and store an NSAttributedString in attributedBody. The Atomic Object note of 07/17/2024 reports the same move and is unsure of the macOS version. A reader that selects only text will miss those rows. The September note says the blob starts with streamtyped and that taking the first string is not a full decode of the stream.

Attachments stay out of the row. attachment.filename is a path. The bytes live in the Attachments directory beside the database.

When it is written or updated

date is the message time, in Cocoa units from 01/01/2001 00:00:00 UTC. The note says values of about 9 digits are seconds and values of about 18 digits are nanoseconds. date_read and date_delivered use the same clock, and a zero means the status was not recorded. date_edited and date_retracted are the note's signals that a sent message was changed or unsent, from iOS 16 and macOS Ventura in that write-up. The row can remain after the content is gone.

SQLite WAL mode means the newest transaction may be in the -wal file. The note says the main file alone can be an older conversation. The -shm file is the third companion it names on the Mac.

What the notes do not settle

Not independently verified

Apple is not the author of either note. Column presence depends on the OS version, which is why the September 2026 note says to read PRAGMA table_info(message) on the file in hand. This page does not extend the column list past what those notes printed, and it does not claim the list matches a current phone.

The backup hash, the paths, and the limit on what a court can be told from a row are on the forensics view.

Indexed under

  • Developers
  • Insights
  • Records

A first-person educational note. Developer insights record something that stuck while learning to build software. They are not Digital Forensics findings, not product claims, and not career advice.

Check your own project by what actually happens when you skip a step. Read how these insights are written.

← All insights