Let's be blunt: Backspace.me has never used Firebase. No FCM tokens, no Google Cloud Messaging, no Play Services push. Not in a previous version, not in a test branch, not anywhere. Calls, messages, and wake-ups have always travelled through our own P2P relay nodes — and today we're shipping the piece that makes it airtight: a native keepalive service built from scratch.
Why Almost Everyone Else Uses Firebase
Firebase Cloud Messaging is the default way to wake a mobile app when something arrives. Almost every chat app on Android uses it, because it's the path of least resistance — Google hands you a push pipe, you hand Google your tokens, and the OS happily wakes your app. Easy. Free. Convenient.
It is also, quietly, one of the biggest metadata leaks in modern messaging. Every time a message or call needs to wake your phone, a push goes through Google's servers — and Google logs the who, when, and how often, even if it never sees the payload content.
That is a compromise we were never willing to make. Backspace.me is built on a simple promise: no metadata exists about you anywhere, at any time. Not on our servers. Not on a relay node. Not on Google's. If we shipped a private messenger and Google still knew when you were getting called, the promise would be broken. So we chose the hard path from day one.
An FCM token is a persistent identifier tied to your device and Google account. Every push through FCM creates a timestamped log entry on Google's infrastructure: token X received a wake-up at time Y. That alone is enough to map call patterns, sleep cycles, and social graphs — without ever decrypting a single message. Backspace will never issue, register, or transmit one of those tokens.
The Firebase Path vs The Backspace Path
Here is the shape of the compromise in one frame. On the left is what almost every other messenger does. On the right is what we do instead — and have always done.
Everyone Else — Firebase
- FCM token registered with Google
- Incoming call → server → FCM → device
- Google logs push timing and recipient
- Third-party dependency on Play Services
- Metadata leak by construction
Backspace — Native Keepalive
- No tokens issued, none to leak
- Incoming call → node → direct socket → device
- No third-party sees any event
- No Google Play Services requirement
- Metadata does not exist to log
NativeKeepAliveService
The heart of our approach is a small, focused Android foreground service we call NativeKeepAliveService. Its only job is to hold a live connection to the Backspace relay mesh for as long as the app process is allowed to exist — including when the user swipes the app away or taps the home button. No Google involvement at any point.
Inside the service, an OkHttp WebSocket maintains a standby socket to a chosen relay node. It is not a push endpoint. It is not polled. It is a persistent, low-overhead bidirectional pipe that our nodes can write to the instant an event needs to reach you — a call, a priority message, anything else that has to break through the device's doze state.
We needed a WebSocket stack that survives network hand-offs, tolerates aggressive battery optimizers, and reconnects fast on flaky carriers. OkHttp is battle-tested in production Android apps at massive scale and gives us control down to ping frames and backoff timing. No third-party SDK, no binary blobs — just a WebSocket client we fully understand, talking only to our own nodes.
Transport: OkHttp WebSocket, persistent
Endpoint: Backspace relay node (chosen at runtime)
Auth: Ephemeral peer key, no server-side account
Dependencies: None from Google Play Services
Dual-Socket Routing
One WebSocket is not enough when you care about latency. When the app is in the foreground and actively chatting, we already hold a primary socket for message traffic. When the app drops to the background, NativeKeepAliveService brings up a second socket optimized for wake-ups. Both stay healthy at the same time.
Routing between them happens in a tiny function called _findBestSocketForPeer. When a node has something to deliver, it inspects the state of both sockets, picks whichever is currently open and freshest, and writes the event into that one. If both are alive, the primary wins. If the primary is gone — backgrounded, dozing, screen off — the keepalive socket takes the hit. The handover is invisible to the user.
A single connection is a single point of failure. With two independent sockets on two independent code paths, a backgrounded app can still receive a call in under a second — and a foregrounded app never pays the latency cost of waking the keepalive path. Best of both worlds, zero duplicated delivery.
The Incoming Call Chain
All of this plumbing exists to solve one very hard problem on Android without Firebase: reliably showing a ringing screen when the app is not running. Android's battery optimizers, the Doze mode lifecycle, OEM kill-happy background managers, and the difference between a cold start and a warm resume all conspire to make this genuinely difficult. Firebase exists precisely because most teams give up and hand that problem to Google. We didn't.
Our call chain looks like this:
- Node signals the call over the keepalive socket that
NativeKeepAliveServiceis already holding. - A CallStyle notification fires immediately — this is Android's high-priority, full-screen ringing intent.
- Warm-resume spins the renderer back up in the background without a full cold start, restoring the peer session.
- acceptCall is wired to the notification action, so the user tapping "Answer" lands directly into a live call regardless of which launch path the OS just took.
We tested this across every hostile path we could think of: cold start (app killed by OS), task swipe (user swiped it away from Recents), and home-button background (classic doze path). All three now land on the same answered call. That is the entire point of the build.
We are not claiming zero bugs forever — we are claiming the wake path is deterministic. CallStyle → warm-resume → acceptCall is the only path. There is no Firebase fallback, no Play Services dependency, no silent failure mode that blames Google when the phone doesn't ring. We own the entire chain, end to end.
Zero Metadata, Even On Calls
This is the part that matters to users who don't care about OkHttp or dual-socket routing. In plain English:
- Nobody outside the Backspace network sees a call happen. Google doesn't see it. Apple doesn't see it. Your carrier sees encrypted bytes, nothing more.
- The relay nodes that carry the wake-up signal don't know who is calling whom. They see opaque routing tokens and encrypted payloads — the same blind-forwarder model as the rest of our messaging stack.
- There are no push tokens to leak. No FCM, no APNs, no third-party registration ID tied to your account.
- There is no call log living anywhere but on your own device. Not on our servers, because we don't run any. Not on a relay, because relays forget everything the moment they forward it.
What This Means For You
Incoming calls on Backspace arrive through a path that never touches Google. Not once, not as a fallback, not "most of the time". Ever. That means there is no "encrypted chat with a metadata asterisk" situation — it really is zero metadata, including call signaling.
If you are one of the people who runs Backspace specifically because you do not want Google Play Services on your phone: the app works. It works on de-Googled Android. It works on GrapheneOS. It works on any Android with no Play Services at all, because there is nothing in our stack that needs them.
The native keepalive is live right now on the latest Backspace.me build. No server migration, no waiting list, no staged rollout — there was never a Firebase layer to remove in the first place. Every call from day one has taken the native path, and today it's bulletproof across every Android wake scenario we tested.
Private calls, no asterisks
No Google. No Firebase. No metadata. No third-party wake-up tokens. Just encrypted signaling over our own P2P nodes, end to end, from day one.