Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/vruizz22/innova-backend-serverless/llms.txt

Use this file to discover all available pages before exploring further.

Production runs on AWS Lambda + API Gateway, deployed via Serverless Framework 3 with esbuild bundling to nodejs20.x. The custom domain api.superprofes.app is mapped to the API Gateway regional endpoint via serverless-domain-manager. The service lives in the us-east-1 region and is the infrastructure authority for all SQS queues and S3 buckets in the platform — any dependent service (innova-ai-engine, client apps) must be deployed after this backend.

Deployment Mechanism

Serverless Framework reads serverless.yml and deploys one CloudFormation stack containing six Lambda functions, all SQS queues, all S3 buckets, and the custom domain mapping. esbuild bundles each handler independently, tree-shaking unused modules and preserving NestJS decorator metadata via a custom plugin (esbuild-decorators.cjs). The six Lambda functions deployed:
FunctionHandlerTriggerPurpose
apisrc/lambda.handlerAPI Gateway (ANY)Main NestJS HTTP application
telemetryWorkersrc/infrastructure/workers/telemetry-persister.handlerSQS FIFO (batch 10)Persists attempt events to MongoDB
llmClassifierWorkersrc/infrastructure/workers/llm-classifier.handlerSQS Standard (batch 20)Routes unclassified errors to Claude
ocrWorkersrc/infrastructure/workers/ocr-worker.handlerS3 ObjectCreatedTranscribes student photo uploads via Gemini
alertGeneratorsrc/infrastructure/workers/alert-generator.handlerEventBridge rate(1 hour)Generates teacher alerts on a schedule
attemptReprocessWorkersrc/infrastructure/workers/attempt-reprocess.handlerSQS Standard (batch 10)Creates Attempt records from graded submissions
This stack owns the SQS queues and S3 buckets that innova-ai-engine consumes. The required deploy order when provisioning a new environment is: backend → ai-engine → clients.
Always deploy the backend first when setting up a new environment. The SQS queue ARNs and S3 bucket names created here are exported as CloudFormation stack outputs (innova-{stage}-LlmClassifyQueueArn, innova-{stage}-GuideIngestQueueArn, innova-{stage}-ExerciseGenerateQueueArn, etc.) and are imported by innova-ai-engine during its own deployment. Deploying ai-engine before backend will cause a CloudFormation import error.

Manual Deploy

Use this procedure for a one-off manual deploy or when bootstrapping a new stage. CI/CD (below) performs exactly these same steps automatically on every merge to main.
1

Build the project

Compile TypeScript via NestJS CLI. This validates types and produces the dist/ output that esbuild ingests.
pnpm build
2

Run pending database migrations

Apply any unapplied Prisma migrations to the production Postgres database. This step is safe to run repeatedly — Prisma tracks applied migrations in the _prisma_migrations table.
pnpm prisma migrate deploy
3

Deploy to AWS via Serverless Framework

Package, upload, and deploy all Lambda functions plus CloudFormation resources. The --stage flag controls the resource name suffix and the NODE_ENV value injected into every function.
npx serverless deploy --stage prod
4

Verify the deployment

Confirm the API is healthy before marking the deploy complete:
curl -s https://api.superprofes.app/health
# Expected: 200 OK
During development you can run the full Lambda + API Gateway stack locally without deploying to AWS. The serverless-offline plugin (already registered in serverless.yml) starts a local emulator:
npx serverless offline --stage dev
This is especially useful for testing Lambda handler behavior, cold-start timing, and API Gateway mapping templates without incurring AWS costs.

CI/CD

Three GitHub Actions workflows automate the quality gate and deployment pipeline:
WorkflowTriggerAction
ci.ymlPull request opened or updatedRuns TypeScript type-check, ESLint, unit tests, and coverage gate (≥ 75%)
deploy.ymlPush to main (after CI passes)Runs pnpm buildprisma migrate deployserverless deploy --stage prod
seed-prod.ymlManual workflow dispatch onlySeeds demo auth users in production via Supabase Admin REST API
All secrets required by deploy.yml and seed-prod.yml are stored as GitHub Actions repository secrets and injected as environment variables at runtime. No secrets are baked into the repository.

Production Configuration Notes

These settings are easy to misconfigure and each one has a significant operational impact:
  • DATABASE_URL must use the Supabase transaction pooler. The backend uses Prisma with the @prisma/adapter-pg serverless adapter. In Lambda, each cold start opens a new TCP connection. Without the transaction pooler (:6543) and the ?pgbouncer=true&connection_limit=1 flags, Postgres will hit its connection limit under modest load. See the Environment Variables reference for the exact URL format.
  • CORS_ORIGINS must list browser origins only. The CORS policy applies to requests made from a browser. The innova-ai-engine service runs as Lambda functions — they call this API server-to-server and never send a preflight request. Do not add ai.superprofes.app to CORS_ORIGINS.
  • All secrets live in GitHub Actions repository secrets. The following secrets must be configured before deploy.yml can run: SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, DATABASE_URL, MONGODB_URI, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, ANTHROPIC_API_KEY, GEMINI_API_KEY, RESEND_API_KEY, RESEND_FROM_EMAIL, PUBLIC_API_URL, PUBLIC_APP_URL, SEED_DEMO_PASSWORD.
  • AWS account and region. All resources are deployed to region us-east-1. The AWS IAM user used by CI must have permissions to manage CloudFormation, Lambda, SQS, S3, and API Gateway in that region.

Release Flow

The project follows a Gitflow-style branching model. The release process after a sprint is complete:
  1. Open a release PR from developmain and get it reviewed
  2. Merge the PR — deploy.yml triggers automatically and deploys to production
  3. Verify the deployment with curl https://api.superprofes.app/health
  4. Back-merge maindevelop to keep the branches in sync
  5. Create a GitHub release and tag on main documenting the changes (see ../docs/DEPLOY_RUNBOOK.md §5–6)

Environment Stages

The serverless.yml accepts a --stage parameter that controls the names of every resource created. This makes it possible to maintain completely isolated dev and prod environments within the same AWS account.
# Deploy a development/staging environment
npx serverless deploy --stage dev

# Deploy the production environment
npx serverless deploy --stage prod
The stage value is embedded in all resource names, for example:
Resourcedev nameprod name
SQS attempt-streaminnova-backend-serverless-dev-attempt-stream.fifoinnova-backend-serverless-prod-attempt-stream.fifo
S3 guides bucketinnova-backend-serverless-dev-guidesinnova-backend-serverless-prod-guides
S3 submissions bucketinnova-submissions-devinnova-submissions-prod
CloudFormation stack outputs (Outputs section of serverless.yml) export queue ARNs prefixed with the stage name so that innova-ai-engine can import them regardless of which stage is being deployed:
Export nameValue
innova-{stage}-LlmClassifyQueueArnARN of the LLM classification queue
innova-{stage}-GuideIngestQueueArnARN of the guide-ingest queue
innova-{stage}-SolutionGenQueueArnARN of the solution-generation queue
innova-{stage}-SubmissionGradeQueueArnARN of the submission-grading queue
innova-{stage}-AttemptReprocessQueueArnARN of the attempt-reprocess queue
innova-{stage}-ExerciseGenerateQueueArnARN of the exercise-generation queue

Build docs developers (and LLMs) love