Skip to content
ameoworks

Engineering demonstration

A matrimony platform, built service by service

Our own product, built from scratch: nine Spring Boot applications and a mobile app, kept in step by one written API contract and locked down with certificates.

What this is. We built this ourselves, for ourselves. It is not a client project, and we do not quote usage or performance numbers.

The problem

A match only counts when both people say yes. So every suggestion has to work from both sides, give newer profiles a fair chance, and respect preferences like community, location and lifestyle.

Behind the screen, the services must trust one another, the apps must stay in step with the backend, and we must hear about a problem before our members do.

How the Ameoworks matrimony platform is structuredMobile and web clients reach a Caddy reverse proxy, then the API gateway and a web backend-for-frontend. The backend-for-frontend calls five business services, each with its own data, over mutual TLS. PostgreSQL, MongoDB, Redis and RabbitMQ sit underneath, and Prometheus, Grafana and Loki watch every service.Mobile app and webCaddyHTTPS, the public doorAPI GatewaySingle entry pointWeb BFFOne API for the appsUserProfileMatchConnectionNotificationEach service owns its data and talks over mutual TLSPostgreSQLMongoDBRedisRabbitMQPrometheus · Grafana · Loki watch every service

What is in it

Engineering decisions

  1. 01

    Look at every match from both sides

    We score each pair from each person's point of view and combine the two with a weighted harmonic mean. That way a match that suits only one person cannot rank high. The scoring is split into small, separate scorers, one for each dimension.

  2. 02

    Fairness is part of the ranking

    Ranking runs in separate stages for exposure, recent activity and verification, and each page is shaped for freshness, variety and a little exploration. Candidate pools mix active, random and new profiles, so a list sorted purely by score does not leave newcomers unseen. We also track how stable the ranking is.

  3. 03

    Prepare the work ahead of time

    A nightly job scores a deep pool and saves the daily picks. Reads come from a Redis cache, are checked again when served, and carry on working, a little more simply, if Redis is down.

  4. 04

    Write the contract first

    Every service starts from an OpenAPI file and generates its controllers and types from it. The front-door service reuses the owning service's response shape instead of copying it. In CI, the specs are linted and a breaking change fails the build.

  5. 05

    Services prove who they are

    Every call between services uses mutual TLS, with certificates from our own authority, and each service keeps a short list of who may call it. Only the reverse proxy faces the internet.

  6. 06

    Send events only after the save

    Events go to RabbitMQ only after the database commit, so a rollback can never leave a ghost message behind. A correlation id travels with each request, over HTTP and over messages, so one user action can be followed end to end.

  7. 07

    Keep the layers clean

    Generated API types stay at the edge, database entities stay inside persistence, and the service layer talks only in validated domain objects. In the user service, automated architecture tests fail the build if a layer reaches where it should not.

  8. 08

    Test it the way it runs

    Tests are written as given, when, then. Integration tests run against a real PostgreSQL that is kept separate from the development one, so a cleanup can never touch real data.

  9. 09

    See problems early

    Every service reports metrics to Prometheus, with Grafana dashboards for each API and one for the sign-up funnel. Logs go to Loki carrying the correlation id, so you can follow a graph down to the exact request.

  10. 10

    Rebuild from nothing, on paper

    Settings live in a config server with separate development and live folders. Secrets come from a secret manager, not from git, and a written runbook describes how to rebuild the whole thing from scratch.

Go deeper

Technology

Facing a similar problem?

Tell us what you are building or trying to fix. We will reply with an honest view.

Discuss your project