Back to selected systems

Full-stack Product · 2025–2026

Ovanta

A cross-region self-service platform for visas, immigration, and overseas identity.

A self-service application platform for Chinese and international users. One codebase powers both regional sites with structured policy content, regional login and payments, and membership entitlements. Live at ovanta.cn.

Problem & responsibility

Business problem: organizing scattered, professional, and ever-changing official policies into auditable, composable structured guides — then completing commercial delivery through subscriptions, payments, and entitlements. I led content modeling, regionalization, and payment idempotency.

System flow

  1. Policy content
  2. Structured modeling
  3. Eligibility check
  4. Subscription & payment
  5. Entitlements
  6. Consulting
  7. Operations loop

Engineering focus

Content System
16 content models and typed components power multiple products and 200+ pages through one editing and publishing flow.
Payment Hook Chain
Payment callbacks pass a blocking hook chain — signature, amount, state machine, and idempotency checks — blocking on write, degrading on read.
Regional Architecture
Both regions share the core business code with build-time regional config and channel adapters, sharply reducing duplicated work.

Evidence

Content Models
16 models · 25 components · 200+ pages
Entitlements
99.9%+ reconciliation · zero duplicate grants across 1k+ replays
Events API
P95 < 100ms · duplicate rate < 0.1%
E2E
Given-When-Then pass rate ≥ 98%

React · Vite · Django · DRF · Strapi · MySQL · PostgreSQL · Redis · Celery · Docker Compose · Cloudflare

Design tradeoffs

  1. Model policy as structured content instead of long-form rich text

    Why
    In a rich-text article it is hard to tell which requirement has gone stale, which version an assessment was based on, and there is no reliable way to gate chapters by membership.
    Cost
    A cross-system boundary forms between Strapi/PostgreSQL and Django/MySQL, and every content-model extension has to change both sides.
  2. Domestic and international sites share core business code, with differences pushed into build-time config

    Why
    Two codebases diverge immediately, and orders, payments, and entitlements are exactly the parts that most need to stay consistent — once split, they never converge again.
    Cost
    Regional differences get compressed into config and adapters, so runtime branching increases; region-specific product asks have to be assessed before they reach the trunk.
  3. Payment callbacks pass a blocking hook chain: signature, amount, state machine, idempotency

    Why
    Payment callbacks durably duplicate, arrive out of order, and arrive late — any missing check turns directly into granted entitlements that should not exist, or missing ones that should.
    Cost
    The callback path gets longer and failure modes need their own degradation and manual-intervention design; reconciliation becomes a permanent independent capability.
  4. Server-side checks are the authority for permissions; frontend display state is never the basis

    Why
    Hiding an entry point in the frontend does not mean the user lacks access — treating display as authorization hands the permission boundary to the browser.
    Cost
    Every feature with a display state re-checks permissions on the server, increasing endpoint count and round-trips.

What this system does not do

Deliberate non-goals. A boundary that is written down is a boundary that can be held.

  • Does not accept or approve applications on behalf of government agencies
  • Does not guarantee visa, immigration, permanent-residency, or account-opening outcomes
  • Does not make professional legal judgments automatically without a factual basis
  • Does not replace consultants for work that requires human judgment and sign-off
  • Does not auto-generate and publish policy content from non-authoritative sources
  • Does not let AI directly modify content, eligibility rules, prices, plans, or entitlements
  • Does not read correlation in operations data as established causation
  • Does not let frontend display state stand in for real server-side permission checks
  • Does not clear payments itself — funds still settle through compliant payment channels

Open questions

What I do not have an answer for yet. Happy to be asked about any of these.

  • Content-model coverage depends on how finely editors decompose a policy, and there is no settled “minimal common model” for cross-region reuse
  • Payment callbacks are down to zero duplicate grants across 1k+ replays by idempotency key, but late-arriving channel reconciliation files still need manual cover
  • How to raise content-production efficiency without crossing the line that policy conclusions require human confirmation — today AI only aggregates on the operations side, which is not automation
  • The regionalization adapter folds differences into config, but each new region still needs its payment channels and compliance requirements assessed individually