← Case studies

Radar Verdict

Multi-tenant B2B SaaS for compliance and supplier risk

Full-stack / product engineer · 2024 – present

SaaSComplianceRAGMulti-tenancy

Background

Compliance teams assess suppliers from documents that never arrive in the same shape twice — certificates, filings, questionnaires, news. The judgement is real work, but most of the day goes to gathering and re-reading rather than deciding.

The goal was a system that does the gathering and first-pass reasoning, then hands a compliance officer a verdict they can audit and override — not a score from a black box.

Approach

I designed the platform as multi-tenant from the first migration, with a clear split between global resources and team-scoped ones, and tenant isolation enforced below the query layer rather than in each handler.

  • RAG over pgvector for retrieval across a tenant's own corpus, with citations carried through to the verdict.
  • An analysis pipeline of composable blocks — each step is inspectable, tunable, and replaceable, so an operator can see why a verdict came out the way it did.
  • Idempotency, audit trails and Paddle billing designed in before launch, so re-runs and money never depend on luck.

Outcome

The pipeline produces verdicts with their evidence attached, and the operator stays in control — every automated step can be tuned or overridden. Because isolation and audit were designed up front, adding tenants and new analysis blocks has stayed a routine change rather than a rewrite.

Iterations

  1. 1.Tenant isolation before the first incident

    Rather than bolt isolation on later, I modelled global vs team-scoped resources from the start and pushed enforcement beneath the API. A shared resource and a tenant's private data follow different code paths that can't be confused by a forgotten where clause.

  2. 2.The analysis pipeline as composable blocks

    The first version was one large routine; it worked but nobody could tell why a verdict changed. I refactored it into ordered blocks with typed inputs and outputs, so each stage is inspectable and an operator can tune a single step without touching the rest.

Stack
Next.jsNestJSPostgreSQLpgvectorPrismaPaddle

Was this useful?

Comments

    Reviewed before it appears. 2000 characters left.

    Comments are public, moderated, and not verified — a name here proves nothing about who wrote it. Your IP is stored as a hash for abuse handling. Please don't post personal data, yours or anyone else's.