Skip to content

Data Layer

The new backend currently uses Prisma as the clearest active persistence layer and appears to be built against an existing MySQL schema rather than a greenfield database design.

This is an important architectural fact:

  • the backend is modern in framework and typing
  • but the data layer is integrating with an already-existing legacy-style relational schema

The backend currently includes:

  • Prisma schema definitions under prisma/
  • Prisma client generation scripts
  • Prisma migrations workflow commands
  • Prisma seeding support
  • a Prisma module and Prisma service under src/database

This indicates Prisma is the primary data access foundation for the new backend.

The most important current files are:

The Prisma datasource is configured as:

  • provider: mysql
  • connection source: DATABASE_URL
  • shadow database source: SHADOW_DATABASE_URL

This means the backend is built around MySQL-compatible persistence and is prepared for migration workflows that require a shadow database.

The PrismaService extends PrismaClient and integrates with the Nest lifecycle.

It currently provides:

  • connect-on-module-init behavior
  • disconnect-on-module-destroy behavior
  • a simple database health-check query
  • logging for connection events

Because PrismaModule is marked @Global(), Prisma is effectively the shared database gateway for all feature modules.

The Prisma schema is not modeling a simple new domain from scratch. It is mapping into an existing database with many legacy conventions.

The strongest signals are:

  • table names remain legacy and pluralized
  • column names are mapped with @map
  • many models use uppercase legacy database columns such as Customer_ID, TimeStamp, or Created_at
  • enums mirror operational business states from the existing system

Examples from the schema:

  • customers.customer_id maps to Customer_ID
  • consultants.order_in_list maps to Order_In_List
  • customers.verified_status maps to Verified_Status

This tells us Prisma is being used as a typed integration layer over an existing schema, not as the original source of naming conventions.

A very important characteristic of the current data layer is that many models appear flat from Prisma’s perspective.

The schema contains many integer reference fields such as:

  • Customer_ID
  • Consultant_ID
  • Branch_ID
  • Category_ID
  • Order_ID

However, many of these are not yet modeled with rich Prisma relations.

The backend currently relies heavily on:

  • scalar foreign-key-style fields
  • manual querying by ID
  • service-level orchestration of joins and lookups

instead of deeply relational Prisma model traversal.

This makes sense when integrating into a large existing database, but it also means:

  • domain relationships are still encoded primarily in naming and service logic
  • not all data integrity meaning is expressed directly in Prisma relations

The Prisma schema already includes a broad set of mapped models, including:

  • customers
  • consultants
  • appointments
  • articles
  • branches
  • careers and career applications
  • collections and courses
  • configuration settings
  • consultant contracts and schedules
  • content and engagement tables

This indicates that the new backend is already wired into a large cross-domain persistence surface, even if only part of it is currently exposed through active Nest modules.

The currently visible services show a simple and pragmatic access pattern.

The reference service reads from:

  • consultations_categories
  • services_categories

It then maps those rows into API response objects, including media URL composition using CONTENT_URL.

The consultants service reads from:

  • consultants

It uses:

  • pagination helpers
  • selective field projection
  • explicit findUnique access by id
  • translation-aware not-found errors

The auth service uses Prisma heavily across:

  • customers
  • consultants
  • consultations_orders
  • consultant_contract
  • token and OTP-related persistence

This is the richest currently visible example of business logic composed directly on top of Prisma queries.

The auth domain provides the clearest view of how the backend currently thinks about persistence.

It combines:

  • persistence-layer types
  • branded domain-level ID types
  • token payload mappers
  • profile mappers for database records

This indicates an attempt to separate:

  • database record structure
  • domain semantics
  • token and session semantics

even though all of them still sit fairly close together in the auth module.

The auth module includes mappers and branded types that sit between raw Prisma rows and application-level behavior.

Examples include:

  • mapCustomerToProfile
  • createTokenPayload
  • branded types such as UserId, ConsultantId, and DeviceToken

This is a good sign that the backend is moving toward clearer domain boundaries rather than passing raw database shapes everywhere.

The backend already includes a seed pipeline through:

  • npm run seed
  • backend/prisma/seed.ts

The current seed behavior focuses especially on:

  • customers
  • consultants
  • auth-related and consultant-eligibility scenarios

The consultant seeder is particularly valuable because it does not only create demo rows. It creates realistic state combinations such as:

  • eligible consultant
  • disabled customer
  • disabled consultant
  • pending order
  • missing contract
  • expired contract
  • missing license
  • expired license
  • missing order

This indicates the seeding layer is being used as a domain-scenario tool for development and testing, not only as static fixture loading.

The backend package exposes Prisma commands for:

  • generate
  • migrate
  • deploy
  • reset
  • studio
  • db pull

This suggests the intended data workflow is:

  1. define or update Prisma schema
  2. generate Prisma client
  3. run migration workflows
  4. seed development data when useful

At the same time, the presence of schema-existing-stg.prisma suggests the team is also working against an already-existing staging schema and may be reconciling legacy and new database representations.

The backend dependencies still include TypeORM, but the actively visible data workflow is Prisma-first.

This creates an important interpretation:

  • Prisma is the practical current data layer
  • TypeORM may be transitional, planned, or legacy dependency carry-over

Until TypeORM is proven active in module code, Prisma should be treated as the real persistence standard for this backend.

The current data layer already has several strengths:

  • type-safe database access
  • migration-driven schema management
  • seedable development environments
  • explicit service-level database usage through NestJS modules

It also provides a clear path away from direct SQL embedded in application logic.

The current implementation also shows some tradeoffs:

  • Prisma is integrating with a complex pre-existing schema, so naming is less clean than a greenfield model
  • many relations are still represented as scalar IDs rather than explicit relational graphs
  • service modules may need to manually compose cross-table logic
  • domain boundaries at the persistence level are improving, but not fully abstracted yet

For documentation purposes, the current data layer should be described as:

  • Prisma-backed
  • MySQL-based
  • legacy-schema-integrated
  • service-composed rather than deeply relation-driven
  • already capable of typed queries, seeded scenarios, and migration workflows

This is the most accurate description of the backend data layer today.