UnifiedPush and Public ntfy.sh: Why Push Notifications Fail on Android Without Google Services
Developers of a messenger operating in a region where Google services are unavailable faced the familiar problem of replacing FCM. The standard open-source answer is UnifiedPush, which splits delivery among the app, the application server, and a distributor that maintains a connection to a push server. The team implemented this approach in June using the popular ntfy distributor paired with the public ntfy.sh instance.
One and a half months later, user complaints about missing notifications prompted an examination of production logs. Over a 36-hour window the server recorded 100 successful deliveries against 507 responses with code 507 (Insufficient Storage), 351 with code 429 (Too Many Requests), and 69 with code 400 (Bad Request). Failures had been present since the feature launch; they simply went unnoticed on always-connected test devices.
The 507 errors stem from a deliberate design choice in ntfy: when visitor-subscriber rate limiting is enabled, a UnifiedPush topic must have an active subscriber before any message can be published. The official ntfy client from Google Play uses Firebase for instant delivery and only maintains a persistent WebSocket when the F-Droid build is used. In regions without Google services the client never registers a subscriber, so every server POST receives an immediate 507 and the message is discarded rather than queued.
Code 429 responses arise because rate-limit buckets are attached to the subscriber’s IP address, not the sender. Mobile carriers place hundreds of users behind a single NAT address; a single group message can exhaust the shared 60-request bucket and cause subsequent deliveries to fail for unrelated users sharing the same IP. Many endpoints alternated between 429 and 507 within a single day, producing the intermittent behavior reported by users.
Endpoints pointing at updates.push.services.mozilla.com returned 400 because the server implements the WebPush specification (RFC 8030), which requires a TTL header. The original implementation omitted the header, assuming ntfy behavior would apply to every endpoint. The team now sends a minimal WebPush-compliant request containing Content-Type, TTL, and Urgency headers for all destinations.
Purchasing a paid ntfy.sh plan does not resolve the problem. Both the subscriber-existence check and the rate-limit logic operate on the recipient side; elevating the sender’s quota has no effect. The developers therefore deployed a self-hosted ntfy instance with visitor-subscriber-rate-limiting disabled, a generous burst limit of 200 requests, and an exempt host list that includes the backend address.
Even a private push server leaves users with the burden of installing and configuring a separate distributor application. To remove this friction the team implemented an embedded distributor directly inside the messenger. The component consists of a BroadcastReceiver that answers REGISTER requests and a foreground service maintaining a WebSocket to the private server. The WebSocket reconnect logic includes a “since” parameter so cached messages are delivered after network interruptions.
Two device-only bugs surfaced during live testing. Re-registration generates a fresh topic, yet the service continued listening on the old topic until an explicit comparison was added. Closing an obsolete socket triggered an onClosed handler that scheduled a duplicate reconnect, resulting in duplicate notifications; a generation counter now prevents the second connection from processing events.
Finally, the push WebSocket must traverse the same anti-censorship tunnel used by the rest of the application. Because OkHttp caches the route at client creation time, the service recreates the HTTP client whenever the tunnel state changes, ensuring notifications remain available even when the primary domain is blocked.
Related articles
WebRTC IP Leaks Explained: Why Disabling the Protocol Harms Anonymity in Anti-Detect Browsers
The article from Aurorium details how WebRTC technology can leak real IP addresses even when users route traffic through proxies. It explains the peer-to-peer mechanics of WebRTC, the role of STUN servers in generating ICE candidates, and why standard TCP proxies fail to handle UDP traffic. Disabling WebRTC via flags or JavaScript extensions creates detectable anomalies that anti-fraud systems flag as non-standard environments. The recommended approach involves native emulation inside the browser kernel so that STUN requests return proxy IPs while preserving full API integrity across workers. Additional leaks through local network addresses, mDNS candidates, and IPv6 are also covered with practical verification methods using tools like BrowserLeaks and CreepJS.
Docx Anonymizer: Open-Source Chrome Extension Uses Fine-Tuned rubert-tiny2 to Anonymize Personal Data Before AI Uploads
A Russian developer has released Docx Anonymizer, a browser extension that automatically detects and replaces personal data in documents using a lightweight NER model before they reach public AI services such as ChatGPT. The tool was created to help organizations comply with Russia’s 152-FZ personal data protection law while avoiding the risks of uploading contracts and other sensitive files to cloud-based LLMs. It runs entirely locally via ONNX Runtime and WebAssembly, requires no network calls, and supports any AI chat interface. The underlying model, rubert-tiny2, was further trained through knowledge distillation on WikiANN, factRuEval, and synthetic business documents, reaching strong F1 scores for person and organization entities after int8 quantization. The extension intercepts text on the fly, performs named-entity recognition in under two seconds for typical contracts, and replaces detected entities with placeholders. The project is fully open source and designed for minimal user friction, addressing the growing problem of employees inadvertently leaking corporate and personal data to public AI platforms.
Hybrid Post-Quantum Message Sealing: X25519 + ML-KEM-1024 in Umbera Messenger with Public Rust Tests
Umbera messenger has open-sourced its cryptographic core and published seven Rust tests that anyone can run to verify its hybrid post-quantum message sealing scheme. The design combines X25519 with ML-KEM-1024 so that an attacker must break both algorithms to decrypt a message. Messages are protected by Double Ratchet for forward secrecy, sealed sender packaging, and per-message ephemeral keys derived via HKDF-SHA256 into AES-256-GCM. The relay server stores only an opaque box identifier and encrypted blob with no sender or recipient fields visible. Media calls use DTLS-SRTP end-to-end while TURN servers see only encrypted datagrams. Addresses for message boxes rotate weekly and are derived solely from the shared secret between the two parties.
Free Ad Blocker for iPhone, Android, and Desktop Uses DNS Parsing Without Libraries and Skips YouTube Influencer Ads From the First Second
A new free ad-blocking solution has been released for iPhone, Android, and desktop platforms. The tool relies on a lightweight DNS parser that operates without external libraries. It includes a dedicated mode for users who already run VPN connections. An accompanying browser extension automatically skips sponsored segments in YouTube videos, even when the advertisement begins at the zero-second mark. The developer describes the technical challenges encountered after launch and the fixes applied to maintain compatibility across operating systems. The project emphasizes user privacy by avoiding unnecessary data collection and third-party dependencies.