Skip to main content

RaR-IT SaaS Platform Architecture Policy

Mandatory Technology & Structural Standards for All Shared Engines and Product Verticals

:::danger Status: PROPOSED — Pending Review, Approval, and Publication Version 1.0 · 25 August 2026. This document is not yet binding — see Section 10. :::

1. Purpose & Scope

This policy establishes the mandatory architectural structure and technology stack for every SaaS system built or maintained under the RaR-IT multi-vertical SaaS program — including the shared platform kernel (@rarit-kernel) and all product verticals (currently AMAAR, Clinivio, EduSuite, Shipping & Transport, and Tourism, plus any future vertical added to the program). It governs backend services, shared engines, and their direct integration points. Separate policies may govern frontend/mobile client technology choices in more detail, but this policy establishes their mandatory baseline (Section 5).

The purpose of this policy is to keep the platform's current five verticals — and any future ones — structurally consistent, avoid duplicated engineering effort across verticals, and ensure that architecture decisions already evaluated once, at real engineering cost, are not silently re-opened or contradicted vertical by vertical.

2. Applicability & Enforcement

Upon publication, this policy is mandatory for all RaR-IT employees, contractors, and any third party performing engineering work on a RaR-IT SaaS system, with no exceptions other than through the formal deviation process in Section 8.

This policy applies to: all new backend services; all new shared engines; all significant refactors of existing services. It does not, by itself, require rewriting compliant existing code predating this policy, but it does apply to any new work on that code going forward.

Non-compliant work merged without an approved exception under Section 8 is subject to being reverted or migration-planned at the responsible team's cost, at the discretion of the Architecture Review Board (Section 9).

3. Platform Structure — Shared Kernel & Verticals

3.1 Shared Kernel (@rarit-kernel)

The platform's shared kernel provides five engines, each published as an npm package under the @rarit-kernel scope, consumed — not re-implemented — by every vertical:

  • @rarit-kernel/entitlements — tenant plans, feature-bundle manifests, per-tenant module gating.
  • @rarit-kernel/iam — authentication, session management, role-based access control (RBAC), and tenant identity (the tenants table lives here; every other engine references it).
  • @rarit-kernel/payment — billing, invoicing, settlement, refund and payout primitives.
  • @rarit-kernel/notifications — in-app, email, and SMS dispatch across all lifecycle events.
  • @rarit-kernel/audit — a single, shared, append-only audit trail across every vertical.

3.2 Product Verticals

Each vertical is an isolated runtime and database, multi-tenant within itself via PostgreSQL Row-Level Security, and structurally required to consume all five shared engines rather than reimplementing any part of their function:

  • AMAAR — Real Estate & Construction
  • Clinivio — Medical / Healthcare
  • EduSuite — Education
  • Shipping & Transport
  • Tourism

Any vertical added to the program in the future is automatically in scope of this policy from its first commit.

4. Core Architectural Principles

The following are mandatory and non-negotiable without a Section 8 exception:

  • Engines are embedded plugins, not standalone microservices — the five kernel engines are Fastify plugins embedded directly within each vertical's own backend process; they are never deployed as separately-networked services unless a specific engine's scale requirements are formally reviewed and an exception is granted.
  • Fastify's plugin encapsulation is a composition boundary, not an authorization boundary — encapsulating an engine as a Fastify plugin controls how code is organized and loaded; it does not, by itself, enforce who is allowed to call it. Authorization is always the Entitlements/IAM engines' responsibility, explicitly checked, never assumed from plugin structure.
  • Tenant identity is owned by IAM, not by any other engine — the tenants table lives inside @rarit-kernel/iam; every other engine (Entitlements, Payment, Notifications, Audit) references tenant identity as a cross-engine logical foreign key, never duplicating or re-defining it.
  • Manifest-driven vs. fixed-contract engines — Entitlements, IAM, and Notifications are manifest-driven (their behavior is runtime-configurable per tenant); Payment and Audit are fixed-contract (their behavior is structurally identical for every tenant). Any new engine capability must be classified as one or the other before being built.
  • Vertical-specific monetization models (e.g., commission/settlement logic, VIP or premium tiers) are configuration on top of Payment and Entitlements, not new engines.
  • Monitoring and observability are infrastructure instrumentation (structured logging plus a hosted APM), not a sixth stateful engine.

5. Mandatory Technology Stack

LayerTechnologyStatusRationale
Language & RuntimeNode.js + TypeScriptMandatoryOne language across backend, tooling, and much of the frontend build chain. TypeScript's static typing is essential at this scale — five engines and five-plus verticals sharing contracts cannot be safely maintained in untyped JavaScript.
Backend FrameworkFastifyMandatoryIts plugin/encapsulation model maps directly onto the "engines as embedded plugins" architecture in Section 4 — an engine is a Fastify plugin, with no translation layer between the framework's modularity primitive and the platform's module boundary. Schema-first validation (JSON Schema + Zod) gives manifest-driven engines a natural validation layer. Lower overhead than heavier frameworks matters at the scale of many tenants sharing backend processes.
DatabasePostgreSQLMandatoryRow-Level Security (RLS) is the platform's core tenant-isolation mechanism — the mechanism every vertical depends on to guarantee tenant A never sees tenant B's data at the database layer, not just the application layer. JSONB supports manifest-driven engine configuration without a schema migration per tenant option. LISTEN/NOTIFY supports lightweight real-time needs without a separate broker.
Web FrontendReactMandatoryEstablished across every vertical's tenant-facing web app; consistent component/design-system reuse across AMAAR, Clinivio, EduSuite, Transport, and Tourism depends on this.
MobileFlutterMandatoryChosen once for the whole platform rather than per-vertical, so patterns proven in one vertical's mobile app are directly reusable in another's.

6. Evaluated & Rejected Alternatives (for the Shared Engines)

The following technologies were formally evaluated for use in authoring the shared engines (Section 3.1) and explicitly rejected in that role. They must not be introduced into new kernel engine work without a new Architecture Review Board decision superseding this section. Section 6.1 below addresses a distinct question — Nest's use in a vertical's own business logic — which was left open, not rejected.

TechnologyStatusReason for Rejection
NestJSRejected for authoring the shared enginesNestJS's primary value proposition — a structured, DI-driven module system enforcing separation of concerns — duplicates what Fastify's own plugin encapsulation already provides for the "engines as embedded plugins" model. Wrapping the engines in Nest would force every vertical to be a Nest application just to consume a shared engine, and would mean engine routes never pass through Fastify's own request pipeline. A fit-for-this-architecture judgment for the engines specifically, not a general verdict on NestJS.
ExpressRejected in favor of FastifySuperseded by Fastify's schema-first validation and materially better throughput at the connection volumes the shared-process, multi-tenant engines need to sustain.
MongoDB / other NoSQL as a primary tenant datastoreRejected for core tenant dataRLS is a relational, PostgreSQL-specific mechanism the tenant-isolation model is built around; a document-store alternative would require rebuilding that guarantee at the application layer, which Section 4 explicitly prohibits.

6.1 Scoped Allowance: NestJS for a Vertical's Own Business Logic

Unlike Section 6 above, NestJS is not rejected as a general-purpose tool. A vertical may use Nest to structure its own app-specific business logic (code that is not one of the five shared engines) once that vertical's complexity genuinely benefits from Nest's module/DI structure. This is a local, per-vertical decision — it does not require Architecture Review Board sign-off on its own, but it is bound by two conditions:

  1. Integration pattern: Nest must be used as a dependency-injection application context only (via NestFactory.createApplicationContext), with Fastify retaining ownership of every HTTP route, the module's feature manifest, and the entitlement-check hook. Nest-resolved services are called from inside ordinary Fastify route handlers; Nest never runs its own HTTP pipeline for tenant-facing traffic under this default pattern.
  2. Manifest compliance: regardless of whether a module's internals are plain Fastify or Nest-organized, it must export the same framework-agnostic feature manifest (key, bilingual display name, required plan, routes) that Entitlements' discovery mechanism already reads for every other module. Entitlements must never need special-case logic to discover a Nest-organized module.

A second pattern — Nest running its own Fastify-adapter HTTP instance, mounted or proxied under the parent process — is technically possible but not the default, because it moves entitlement enforcement out of Fastify's own request pipeline. This second pattern requires Architecture Review Board sign-off before use. See Annex A for worked code examples of both the permitted pattern and this restricted one.

If the shared engines are ever split into independently-deployed microservices in the future (an explicitly open possibility, not a current plan), this calculus changes — that is a future-state trigger for revisiting this section, not a basis for adopting it today.

Unlike Sections 5 and 6, the following are the platform's current defaults but may be replaced by a team for good technical reason without a full Architecture Review Board exception — a lighter-weight notification to the platform architecture owner (Section 9) is sufficient.

ComponentCurrent DefaultMay Be Replaced By
ORM / query layerDrizzle ORMAny type-safe, SQL-first TypeScript query layer (e.g., Kysely). Full ORMs that obscure RLS-relevant queries are discouraged, not banned, and need Section 8 review.
Background job queuepg-boss (PostgreSQL-backed) or BullMQ (Redis-backed)Either is acceptable by default; choose based on whether Redis is already needed for another reason.
Schema validationZodAny TypeScript-first schema validator compatible with Fastify's validation hooks.
API documentationOpenAPI/Swagger generated from Fastify schemasMust be generated from the same schemas used for runtime validation, not hand-maintained separately.

8. Exception & Deviation Process

Any deviation from Section 5 (Mandatory) or Section 6 (Rejected) requires:

  1. A written proposal stating the specific technical constraint that the mandatory/rejected choice cannot satisfy — not a preference-based justification.
  2. Review and sign-off by the Architecture Review Board (Section 9).
  3. Documentation of the approved exception in this policy's own change log, including scope (which service/vertical — not a platform-wide reopening) and an expiry/review date.

Exceptions are granted per-service, not platform-wide, and do not set precedent for other services without their own review.

9. Governance & Ownership

This policy is owned by CTO. The Architecture Review Board consists of CTO plus one senior engineer per active vertical]. This policy is reviewed at minimum every two quarters, or immediately upon any Section 8 exception being granted, to determine whether the exception should instead become a policy update.

10. Policy Sign-off

By signing below, the undersigned parties approve this policy as a mandatory standard, effective from its official publication date.

RoleNameSignatureDate
Chief Technology Officer
Vertical Lead (AMAAR)
Vertical Lead (Clinivio)
Vertical Lead (EduSuite)
Vertical Lead (Transport)
Vertical Lead (Tourism)

:::info Signed record Once signed, the approved PDF/DOCX for this version is filed under signed-records/saas-architecture/ in this repository as the immutable controlled copy. This Markdown source continues to evolve toward the next version. :::