Case Studies

SalafiMatch: What a Matrimony Platform Costs You in Moderation, Privacy and Bandwidth

Aman MaqsoodCo-Founder & Chief Executive Officer4 min read

The short answer

SalafiMatch is a matrimony platform with a Flutter app, a Node and MongoDB backend and an administration panel. The engineering that dominates a product like this is not matching. It is photo privacy, verification document handling, moderation tooling and image bandwidth, because every one of those is a place where a mistake harms a real person rather than degrading a metric.

The short version

People create a profile, are verified, browse matches, and talk. Described that way it sounds like a directory with a chat feature.

What it actually is: a system holding identity documents and personal photographs for people who care intensely about who can see them, in a context where a privacy failure is not an inconvenience but a serious harm to someone's family life.

Four problems that shaped the build

1. Photographs cost money every time they load

Profile photos are disk-cached on the device. Without that, every image is fetched again on every scroll and every app open, which costs members their mobile data and costs the business object storage egress for the same bytes repeatedly.

On a browsing-heavy product this is one of the highest-leverage decisions available, and it is invisible in a demo. It shows up in the storage bill and in reviews from people on limited data plans.

2. Login tokens were sitting in plain text

The authentication token originally lived in standard preferences storage as plain text. It was moved into the platform secure store, backed by the Android keystore and the iOS keychain.

Worth stating plainly because it is a common shape of defect: something reasonable early on that becomes indefensible once the account it protects holds verification documents.

3. Photo privacy has to be enforced server-side

The backend carries a maintenance script for backfilling blurred profile pictures, and another for migrating legacy verification documents into their correct handling.

The presence of those scripts is the real lesson. Privacy rules introduced after launch do not apply themselves to data that already exists. Somebody has to write the migration, run it carefully, and verify it, and that work is invisible in every feature list.

4. Moderation accumulates whether you tooled for it or not

There is a script for ensuring moderation indexes exist and another for clearing a report backlog, with a dry-run mode.

A report backlog is what happens when reporting shipped before the tooling to action reports. Every user-generated content product reaches that point. The ones that planned for it have a queue and an index. The ones that did not have a database query someone runs by hand at midnight.

The shape of the system

PieceStackHandles
Mobile appFlutter, Android and iOSProfiles, browsing, chat over sockets, local cache
BackendNode and Express with MongoDBAuth, profiles, matching, payments, moderation, notifications
Admin panelWebVerification review, reports, member management
StorageS3-compatible with presigned URLsPhotographs and verification documents

Error monitoring, rate limiting, security headers and validation are present rather than deferred, and there is an observability document in the backend repository. On a product handling identity documents, those are not optional extras.

When the ecosystem does not fit, vendor the package

One dependency was vendored into the repository to fix a layout fault the package could not express: a field typed too narrowly to accept a flexible child, placed in a row where nothing was allowed to give way. The vendored copy differs from upstream in exactly one file, and the change is marked in the source.

That is the correct way to do an unpleasant thing. Fork narrowly, mark the change, and leave the next person a trail rather than a mystery.

What we would tell you if you were building this

  1. Budget for moderation before you launch reporting. A report button with no queue behind it creates a backlog and a liability at the same time.
  2. Decide photo privacy rules before the first upload. Retrofitting blurring or access control means writing migrations against real user data, which is slower and riskier than getting it right once.
  3. Cache images on device from day one. It is a small change that reduces both your storage costs and your users' data usage, and it is painful to add later.
  4. Put credentials in the platform secure store immediately. It is a few hours of work and it is the difference between an incident and a non-event.

Frequently asked questions

What is the hardest part of building a matrimony or dating app?
Not matching. It is moderation tooling, photo privacy, verification document handling and image bandwidth. Those four determine whether the product is trustworthy and whether it is affordable to run, and all four are invisible in a demo.
Why does image caching matter so much?
Because browsing is the main activity. Without an on-device cache, every scroll refetches images the user has already seen, which consumes their mobile data and generates storage egress charges for identical bytes. It is one of the highest-leverage decisions in the whole build.
Where should authentication tokens be stored?
In the platform secure store, meaning the Android keystore or the iOS keychain, never in ordinary preferences storage as plain text. On an account holding verification documents this stops being a best practice and becomes a requirement.
What happens if you add privacy rules after launch?
You write migrations. Existing photographs and documents do not retroactively obey a new rule, so somebody has to backfill them carefully and verify the result. Planning the rule before the first upload avoids that entirely.
Is it ever acceptable to fork a third-party package?
Yes, when the fault cannot be expressed through the package's API. The right approach is to vendor it, change as little as possible, mark the change clearly in the source, and record why. One marked file is maintainable. A silently modified dependency is not.

Talking about product engineering?

A long-running team that owns discovery, delivery and iteration — for products that keep evolving after launch.