Open Free and open source — read the code

What the server keeps

Encryption keeps your words private. It doesn't hide that you had a conversation at all — someone running the server can still see that a message went from you to someone else, and when. Here is everything the server keeps, and how long it keeps it for.

The short version

  • The server keeps who a message is for and when it arrived, because it cannot deliver it otherwise.
  • It keeps the message itself, still locked, until your app collects it — and it holds nothing that would open it.
  • It keeps your account details: username, email, password (stored scrambled), and the public half of your keys.
  • It does not keep a record of when you added a friend, blocked someone, or joined a group. Those were removed on purpose.
  • Its own logs contain no account, device or address unless an operator deliberately turns on detailed logging.

The rest of this page is the same answer with every field spelled out.

Held while a message is in flight

The numbers below are read from this server's running configuration when the page is served — they are what this instance does, not what a document once said.

KeptWhy it has to beGone after
Recipient account and deviceAn envelope cannot be delivered without an address1 day(s) once delivered
Arrival time and approximate sizeOrdering, and the size is the ciphertext itself1 day(s) once delivered
Sender account and deviceIdentified sends only — a sealed send stores neither1 day(s) once delivered
The ciphertextIt is the message; the server holds no key that opens it30 days if never collected
Attachment blobs (photos, voice notes, stories — all ciphertext)Devices fetch them separately from the envelope that references them30 days
“This one is urgent” — a flag on the envelope, not storedA call has to ring while it is still ringing, so the sender tells the server to push at high priority instead of waiting for the app to poll. In practice that means the server can tell a call from a message — not who is calling, or about what, but that this one is time-critical. It is the single most informative thing a sender chooses to reveal, and it is a choice: nothing forces the flag on.Never written down. It is read to decide the push and then it is gone with the request.
“This one needs no attention” — the same shape, not storedThe other side of the same coin: the sender says an envelope is housekeeping rather than something a person should be interrupted for, so the server sends a background wake instead of an alert. That tells it roughly as much as the flag above does, inverted. The alternative — sending nothing and letting the app decide after it decrypts — means relying on silent pushes that iOS throttles, so the honest trade is a small disclosure for notifications that actually arrive.Never written down, same as above.
Sign-up throttle counters (per IP)New accounts are limited per address per hour, and a counter needs the addressone hour — the counter lives only for its window

Held for as long as the account exists

KeptWhy
Username, email, password hash, display nameIt is an account
Public keys per deviceThey are published on purpose — that is what a prekey bundle is
Buddy list — until you take it offPresence is shown only to people on your list, so the server holds it to enforce that. Settings offers "Take my contact list off the server": the list then lives only in your devices' encrypted stores (and rides your encrypted history export), and the honest cost is that buddies see you as offline — a presence design that needs no stored graph is the planned replacement.
BlocksThe server enforces them, so it has to know them. It cannot enforce one against a message that does not name its sender — blocking someone also cancels the passes you gave them, which is the part that can be aimed at one person.
Who is in each groupNot in the clear, as of 2026-09-04 — and this row used to say the opposite, because it was true when it was written. The server keeps each group’s member list encrypted, with no account numbers in it anywhere: members are known to it only by random tokens it cannot tie back to anybody, and the list itself is a blob it has no key to. The half that was missing is done: the apps now make groups that way, and the old plaintext table is empty — measured, not assumed. Here is the honest shape of what that buys, which has not changed. It protects you from a copy of this database being stolen, or being handed over — the ordinary way this kind of thing actually goes wrong, and worth having. It does not hide your groups from whoever is running the server while it runs, because messages are addressed to each device: watching who receives a group’s traffic still gives the group away. So the promise this earns is “a dump of this database does not reveal your groups”, and not “the server cannot see who you talk to”. Those two sound alike and are not, and we are not going to blur them.
What each group is calledNot held. It used to be, and it should not have been: the name sat in a column the server never actually used for anything, so “Chemotherapy support” or the name of a union drive was sitting on a machine that can be broken into or handed a court order, and it bought nobody anything. It is gone, and the names that were already stored were deleted rather than just stopped. The only places the name can live now are the phones of the people in the group, which tell each other over the same encryption everything else uses. Two things follow, and neither is hidden from you. The app half of this is out now on Android, and comes to iPhone once Apple approves the build that carries it — until it reaches your phone, every group reads as “Group”, which is the server declining to answer rather than anything lost. And a group you made before the change shows as “Group” until somebody in it renames it, because the old name was deleted here and no phone had ever been given a copy: there is nothing left to restore it from. Renaming arrived in that same version, for exactly this reason.
PresenceCoarsened to the online window before it is written, never to the second
Delivery-key digestThe hash only. The key itself never reaches the server except inside a sealed submission
Per-device last-activity stampCoarsened to the hour before it is written. It exists so a device that falls silent for 90 days can be expired — its keys unpublished, its queued mail deleted — rather than staying addressable for ever. An account's newest device is never expired, and an account holds at most 6 devices.

Held for ever, on purpose

The key transparency log: which public keys an account published, and when each device was added, revoked, or expired. It is append-only and permanent because its entire value is that it cannot be quietly rewritten — it is how your app detects a server showing different keys to different people. It contains public keys and lifecycle events only — which account, which device, which kind of event, when — and nothing else: no addresses, no request metadata, no message rows. Those fields are the chain; there is no operational residue riding along with it.

Deliberately not kept

These were removed rather than retained. Each was written and never read, which made them a durable record of how a social graph formed in exchange for nothing:

  • Who uploaded an attachment. The load-bearing one: a sealed envelope stores no sender, and then the attachment it pointed at named the uploader for the life of the blob.
  • When a buddy was added.
  • When a block was set.
  • When someone joined a group.

Push notifications

Android needs no push service: the app holds its own connection to this server, and no third party is involved. On iOS the wake-up goes through Apple, and what Apple sees is held still by a test, not a promise: the payload is the fixed strings "Flamenet" and "New message", a sound, and at most a count of waiting envelopes — never a sender, never a thread, never a word of content. Apple learns that a device was woken and when; the device then collects and decrypts its mail itself and writes its own banner. The push token is stored per device and deleted on sign-out, and when Apple reports the app gone.

Logs

At its default level the server logs operational lines that name nobody: start-up, the hourly retention sweep's counts, and refused requests — with any account or device id in the request's path masked before the line is written, because who was refused is exactly what must not accumulate in a file nothing sweeps. Below that, debug has to be switched on deliberately: it records full request URLs and every database query, and a protocol URL contains a device id, which would turn the log file into a durable record of who fetched whose keys.

Whatever sits in front of the server keeps its own access log. That is the operator's to configure, and on a server you run, the operator is you. On the server operated at this domain, the edge proxy's access log is erased weekly — connection addresses at the front door live for at most seven days.

What none of this changes

A server necessarily observes the connection that delivered a message, including its address. Sealed sender removes the sender from the stored row, not from the network. Anyone claiming a hosted messenger is metadata-free is describing something else.

See also the privacy policy for the retention windows in full, and self-hosting for how to change them.