Yupsly

Private chat · Indonesia · Android

Talk to one person. Not to an ad system.

Yupsly is a private 1-on-1 messenger. You save people by their account id, give them a name that only your device ever sees, and chat. There is no feed, no discovery, no phone number and no password. The app is being rebuilt around end-to-end encryption: the server-side contract is in place, the client implementation is in progress.

Status Server: shipped schema migrated, key routes live, 206 HTTP assertions passing. Android client crypto: in progress no device produces real ciphertext today.

Last updated: 2026-11-15

The product, in one screen

You open the app, you see your chats, you tap a person, you write. That is the whole product, and it is deliberate: the features that turn a messenger into a social network were removed rather than hidden.

Identity

An account is a key, not a password

Your account is a P-256 keypair generated on the phone. Signing in means signing a 60-second challenge with it; the private half stays non-exportable inside AndroidKeyStore behind a biometric-gated master key. Nothing is sent that could be brute-forced, because there is nothing to send.

The honest cost: there is no email, no password and no reset. If you lose the device key before backing it up, the account is gone. The upgrade path is the encrypted backup file, not a support ticket.

Contacts

Save a person by their account id

Accounts have a short handle — seven characters, no look-alike digits — that you can say out loud. You look someone up by it, and you give them a name. That name, and the whole contact list, lives on your device: the server stores no aliases, so nobody else ever sees the nickname you chose.

Conversations

One thread per pair of people, ever

Opening a chat with someone you already have a chat with continues that thread; the database will not fork a second one. Messages sync by rowid, so re-reading a chat costs only what is new.

Three things Yupsly does

1 · Private chat

Text that the server stores without reading in progress

Since 2026-11-15 the API stores an opaque envelope per message and hands it back unchanged. No route parses a message, decodes a key or verifies a signature — that is the server half of the design, and it is built and tested. The device half — the X3DH handshake and Double Ratchet that produce the ciphertext — is being implemented now, so messages are not end-to-end encrypted on any device today.

One visible consequence already: the inbox no longer shows a preview of the last message. The column that held the first 160 characters of everyone's conversations was deleted rather than repurposed.

2 · Files and images

Encrypt before upload, decrypt only to show a preview planned

The design: a fresh random key per file, the file encrypted on the device before it leaves it, that key wrapped for the recipient inside the message, and EXIF stripped by re-encoding before encryption. The recipient downloads ciphertext and opens it locally.

Transport ceiling: 25 MB per file. That is the limit the platform can actually honour — a Worker's request body ceiling on a Free/Pro zone is 100 MB, and pushing 100 MB through an isolate with a 10 ms CPU allowance is not a promise worth publishing. The per-file number in the paid plans below is the target, not the enforced cap. The upload route itself is not built: the only objects in storage today are profile avatars.

3 · Custom encryption

Pick a profile per conversation in progress

Encryption profiles are the part you choose, and they are parameters, never keys: which cipher, how often the ratchet rotates, and whether a one-time prekey is mandatory. standard is safe defaults with zero setup and is what every new account gets. strict requires a one-time prekey and refuses to send when the pool is empty instead of quietly downgrading. ephemeral is the third profile in the same set.

A conversation records the profile chosen when it was opened, but every envelope also names the profile that message actually used — so switching mid-conversation is a visible fact, not a decrypt failure that eats your history.

What makes a profile worth choosing? Most messengers give you one setting: encrypted, or not. Yupsly gives the people who care a dial — and keeps it a dial rather than a knob: the server never holds anything that a profile could leak, because the server never holds plaintext at all. The protocol behind this — including the two places where we deliberately depart from Signal's design and what that costs — is in the whitepaper.

What Yupsly is not

A short list, because "what is not here" is the part most privacy pages avoid.

No ads

There is no advertising code anywhere in the project, and there is no plan for any.

No discovery

People Nearby was deleted on 2026-11-15, along with the friend graph and the Stories feed. Retired paths answer 404 and a test asserts that. You cannot browse strangers; you add someone whose id you already have.

No feed

No posts, no fan-out, no timeline, nothing that ranks your attention.

No location

Not "location off by default" — the permission, the provider, the columns and the endpoint are gone. The app asks for no permission at all on a fresh install.

No phone number, no email

Nothing to verify, nothing to leak in a breach, no SIM to buy. Your account id is a public key, and the only lookup is an exact handle.

No realtime layer

No WebSocket, no push, no typing indicator, no group chat, no iOS. Polling only, and the reason is on the next section.

Android only for now: minSdk 24, release APK about 2.2 MB.

Where it runs, and what that buys you

The backend is one Hono app on Cloudflare Workers with D1 for rows and R2 for avatar objects. There is no server we own, no machine to log into and no long-lived process.

Isolates, not boxes

Code runs in short-lived V8 isolates. There is no operating system for us to patch and forget, and no process sitting around holding your messages in memory.

TLS every hop, secrets kept out of the repo

Transport is TLS throughout. Configuration that must stay private lives in Cloudflare's per-Worker secret store; the repo keeps an example file and the real one is gitignored, so a signing secret is never a committed string.

Limits applied before our code runs

Edge DDoS protection and the platform's native rate-limit binding push abuse back at the network edge, ahead of the application — including the signup ceiling: three new accounts per network per day, then a three-day block.

Cost as a privacy argument

An active user is roughly 35–45 requests a day: a 60-second poll with a chat open, 180 seconds on the inbox, zero while backgrounded, and delta sync that reads only new rows. That is what makes a free-tier private chat app viable without investors or ads — the app does not need to monetise your data because it barely costs anything to run.

The honest half of this section

Running on Workers is not, by itself, a security property. The protection comes from where encryption happens — on your device — not from the host. Because the client encrypts, the Worker never receives plaintext, so a database dump yields ciphertext plus metadata rather than conversations. But the platform choice cuts both ways: it shrinks the surface (no OS to patch, no process to read, no box to log into), while Cloudflare — or anyone who compromises or is served a legal order against this account — can still see metadata: who talks to whom, when, how often, how big each message is, and how many you have unread. A server could also hand both of you freshly forged key bundles; our own tests do not catch that, and the only real defence is the out-of-band safety number.

Short version: we chose a host that gives us a small, cheap, boring surface. The privacy comes from the crypto on your phone. Details, threat model and named deviations: the whitepaper.

Free and paid

Free is not a demo. Encryption, unlimited text and one custom profile are in the free tier and are not for sale.

Plans as decided for the Indonesian market. Prices in rupiah (IDR); billed through Google Play.
What you get Free Plus Pro
Price Rp0 Rp29,000 / month
Rp249,000 / year
Rp49,000 / month
Rp449,000 / year
Default end-to-end encryption for text, images and files in progress Yes Yes Yes
Unlimited text messages (anti-spam rate limits apply) Yes Yes Yes
Custom encryption profiles 1 basic 2 All
Key verification Basic safety number Basic safety number Advanced
Encryption indicator planned Yes Yes Yes
Media auto-delete Yes Yes Yes
Media storage per month planned Basic 5 GB 10 GB
Per-file size planned 25 MB transport ceiling Larger cap (target) Larger cap (target)
Message retention planned Until you delete 30 days 90 days
Encrypted account backup — Yes Yes
Devices planned 1 1 Multi-device
Custom disappearing messages planned — — Yes
Extra screen security (blur in recent apps) — — Yes
Support Email Email Priority

Media top-up, no subscription required: Rp15,000 per 1 GB. Local payment methods — QRIS, GoPay, OVO, DANA and virtual accounts — arrive through Google Play, so there is no second payment integration to trust.

What is enforceable today, versus what is a published target

  • Media quotas, retention windows and disappearing messages are plan targets. There is no media upload route in the backend yet — the only objects in storage are avatars — and nothing currently expires messages on a schedule.
  • Per-file size: the real enforced number we will publish is the 25 MB transport ceiling. Tier-specific larger caps are targets; publishing "100 MB per file" while the platform cannot honour it would be exactly the kind of overclaim we are trying not to make.
  • Multi-device has a server-side basis — up to five keys can be enrolled per account and a second key can be revoked without killing the others — but the sync behaviour that would make it feel like multi-device is not built, and your contact list is device state, so it does not travel with you.
  • Encrypted account backup is the closest thing to shipped in this list: the backup envelope format and the on-device and chosen-file destinations are implemented and were driven on a real emulator. The Google Drive destination has never been tested against a real account.
  • Premium features themselves are gated by client-only billing (next section), which is a deliberate decision with a known cost. Read that section before treating any tier as a hard guarantee.

Billing is client-only, on purpose — and here is what that accepts

Purchases go through the Google Play Billing Library inside the app. There is no server-side purchase-token verification, no Worker endpoint that asks Play whether a receipt is real. This is a product decision made for simplicity, not a gap we have not noticed.

What this gives up

  • A modified APK can unlock premium features locally, on that install.
  • Purchase tokens can be spoofed, because nothing checks them server-side.
  • Refunds and cancellations are noticed only the next time the app is opened.
  • There is no purchase audit trail on our side — we cannot tell you what you bought.

The trade we chose: less moving code, no payment state to keep correct, nothing new for an attacker to break into on the server, and the money still goes to the same place. The upgrade path is one Worker endpoint that verifies a token with Play; when we build it, we will say so here rather than quietly change the wording.

Nothing in this list affects message confidentiality. Abuse of the billing check gets someone a feature flag on their own phone — it does not hand anyone a key, a plaintext or another person's data.

Read the protocol before you trust the product

The whitepaper documents the handshake, the ratchet, the primitives, the threat model — and both of the places where this design deliberately departs from Signal's, each with the reason and the residual risk left in.

  • What the server stores, verbatim, including the exact message envelope.
  • Why one key signs two protocols, and what breaks if the domain prefix is removed.
  • Why the server never verifies a signature, and what that leaves for you to check.
  • What is verified by tests today, and what is not verified at all.

Contact

Questions about the protocol, a tier, or a security report: support@yupsly.id. Product site: https://yupsly.id. API: https://api.yupsly.id. There are no other official Yupsly accounts — no social profiles to impersonate.