← Back to Pollis

Subprocessors

Every third party that touches Pollis, what each one actually sees, and where it runs.

No third party on this page can read a message. Message content is end-to-end encrypted under MLS and the keys never leave your devices — that part is cryptographic, not a policy promise, and it is the same for every row below.

What they do see is metadata, and that varies a great deal. One of them sees your email address and your one-time login code in plain text. Another sees which conversation had activity and when. The table says which is which, because "we can't read your messages" is a much smaller claim than most products let it sound.

Who sees what

SubprocessorRoleWhat it can seeWhere
Turso
libSQL
Metadata database and encrypted-envelope store In the clear: account records including your email address and username, group and DM membership, blocks, conversation timestamps, device registrations, security events, and the connecting IP.
Ciphertext only: message bodies. Since sealed sender landed, the stored row no longer records who sent what.
AWS us-east-1
Cloudflare
Workers & Containers
Hosts the Delivery Service — the only writer to the database Every write as it happens, including the sender's identity, which is authenticated live on each request. Sealed sender is an at-rest guarantee, not an in-flight one, and this is where that distinction bites. Also the connecting IP, as any edge does. Cloudflare's global network; placement is not pinned
Cloudflare R2 Attachments, download CDN, transparency-log hosting Encrypted attachment blobs, their size and upload time, and an object key derived from the content hash — no filename, no user or conversation id. Avatars and group icons are an exception: they are not encrypted and are public to anyone with the URL. Cloudflare global
Resend Sends the login email Your email address and your six-digit one-time code, both in plain text, for the duration of the send. This is the single largest plaintext exposure in the system. The message is sent by the Delivery Service; the app never holds a Resend credential. Provider-determined
Expo
then Apple APNs / Google FCM
Background push notifications Your device's push token, a fixed string ("New message"), the conversation id and whether it is a channel or a DM. No content, no sender, no preview. Not a bare wake signal either: it says this device had activity in this conversation at this time. The push is sent by the sending device directly, so Expo also sees the sender's IP address — it is deliberately not routed through the relay overlay, and moving it server-side is a known open item. Provider-determined
Amazon Web Services The relay pool, its signed directory, and the control plane A relay sees the ciphertext it forwards and the two ends of its hop — so the first hop sees your IP, and every hop learns which account built the circuit, because each hop verifies your device certificate. Never content. See the roster below. Nodes across four US regions; control plane us-west-2
A single leased virtual server Runs the self-hosted LiveKit media server and TURN relay Who is in a call, which room, when, and your IP. Call audio and video are end-to-end encrypted and forwarded as ciphertext, but the realtime signalling JSON is not encrypted at the application layer. No call record is written to any database. One host, one location
GitHub Source, CI, releases, container registry No user data. It is, however, inside the publishing trust boundary: the transparency log is built and signed in GitHub Actions, and the release-signing keys live there too. Assurance covers what that does and does not mean. Global
Apple · Microsoft Code signing and notarization for macOS and Windows builds Build artifacts. No user data. Global
Sigstore
Fulcio & Rekor
Keyless signatures and build provenance Artifact digests and the build workflow's identity — deliberately public, in an append-only log Pollis does not operate. No user data. Global
Doppler Secret management for server credentials Service credentials. No user data. Provider-determined
Where this list ends

There is no analytics, telemetry, crash-reporting or advertising subprocessor, and no payment processor. That is not a policy statement — there is no such SDK in the codebase.

These providers' own operational data is theirs, not ours. Cloudflare edge logs, Turso platform logs, the media server's telemetry and APNs/FCM delivery records are governed by those companies' policies. This page describes what Pollis retains and what each party can observe; it cannot promise what they keep.

Your recipients are not a subprocessor, but they are a limit. Delivered messages live in recipients' local encrypted databases, and there is no mechanism to reach them.

The relay pool, and who operates it

Pollis has an optional relay overlay that hides your IP address from the first-party services. It is worth being blunt about its status and its shape, because the design documents describe an arrangement that is stronger than what currently runs.

It is opt-in and off by default. Unless you have turned on network privacy in preferences, none of your traffic goes through a relay and this section does not apply to you.

The pool is currently switched off. No relay nodes are running. The pool was small and barely used, and it was costing money to leave up, so it was taken down rather than left running as decoration. If you have network privacy set to off or prefer, nothing changes for you — prefer simply connects directly, which is what it already did whenever the pool was unreachable. If you set it to strict, sending will pause rather than connect directly, which is exactly what strict is for; switch to prefer if you would rather keep sending. The table below describes the pool as it was configured and as it will be again if it is switched back on.

What the design allows forWhat runs when the pool is on
Operators Guidance for self-hosters is to run nodes across at least two unrelated providers, so one provider's outage or subpoena cannot take the pool. Every node is first-party, in one AWS account. The two-provider guidance is advice to third parties running their own; it is not a description of the Pollis pool, and it should not be read as one.
Jurisdiction Placement is drawn from an allowed region set with a jurisdiction denylist available. Four US regions — Virginia, Ohio, California, Oregon — with the denylist currently empty. All nodes are therefore in the United States.
Placement A pool-wide node count, not a per-region map. Each node's region is redrawn at random every 24 hours, sampling with replacement — so two nodes in the same region is expected, not a fault. There is no stable per-region roster to publish.
Size Floor of 2 nodes, hard cap of 3, bounded by a $20/month budget. Small, and openly so. These are the cheapest ARM instances AWS sells, bought on spot pricing.
Control plane Subject to the same jurisdiction policy as the nodes. In us-west-2. It sees every relay's IP.

Check the roster yourself

The directory is public and signed. You do not have to take the table above on trust:

curl -fsSL https://relays.pollis.com/directory.json \ | jq -r .payload_b64 | base64 -d \ | jq '{issued_at, expires_at, relays: [.relays[] | {addr, region}]}' Returns the pool with each node's address and region. While the pool is switched off this returns the last directory that was signed, and its expires_at is in the past — an expired directory is one every Pollis client refuses, which is the point: there is no way for a stale roster to keep being used. When the pool is on, placement rotates daily, so what you see will differ from what anyone else saw yesterday — that is the design working, not drift.
Where this guarantee ends

A pool of only first-party nodes is still one operator at both ends. Multi-hop routing means no single node holds both your IP and your destination — but with a first hop and a last hop we both run, those two logs can in principle be joined. What genuinely breaks that is a middle hop in a different trust domain, which is why volunteer relays exist in the design and why a volunteer is never given the first or last position. Today there are no volunteer relays.

This is network-address unlinkability, not anonymity. Every hop verifies your device certificate, so every hop learns which account built the circuit. Hiding the account needs anonymous credentials, which are not built.

An observer who can watch both ends of a circuit can correlate it by timing and volume, regardless of how many hops it has. No overlay of this kind fixes that.

The whole pool currently shares one QUIC identity certificate, so the client pins the certificate rather than any address.

The directory-signing key is Ed25519, not post-quantum — a deliberate exception to the post-quantum migration, because the signer runs in an environment with no ML-DSA implementation. And one key signs both the directory and the revocation list, so a signature proves who signed but not which document was signed.

Push notifications bypass the overlay entirely. See the Expo row above.

Overlay design · Relay operations · Security whitepaper.