Skip to content

Architecture

How the Changineers Platform is built: multi-tenant AWS-native SaaS with no persistent compute under Changineers management.

The Changineers Platform is a multi-tenant SaaS built on AWS. It follows the AWS Well-Architected Framework and the Serverless Application Lens, using AWS managed services wherever possible so that operating-system and infrastructure patching is handled by AWS. There is no persistent compute under Changineers management.

The platform runs in AWS ap-southeast-2 (Sydney) across multiple Availability Zones. Customer content, CMS data, recordings, and other durable assets are replicated to ap-southeast-4 (Melbourne) for disaster recovery.

The platform is multi-tenant. Each tenant is served on its own subdomain and is isolated across three layers:

  • A dedicated AWS Cognito user pool per tenant.
  • Tenant-scoped API routing at the edge, so each tenant has its own origin path through CloudFront and API Gateway.
  • Tenant-column isolation in the relational database, following the “pool” model described in AWS’s SaaS Tenant Isolation Strategies whitepaper. Postgres Row-Level Security enforces the tenant boundary in the database itself: queries cannot reach another tenant’s rows, even if application code asks. The current tenant is set per transaction; without it, the policy matches no rows.

User authentication is handled by AWS Cognito. Cognito stores and encrypts credentials at rest and enforces password policies.

Cognito’s Advanced Security Mode is enabled on every tenant user pool. This provides:

  • Detection of credentials seen in published credential leaks, with a forced password reset when one is matched.
  • Adaptive authentication, which risk-scores sign-in attempts based on device and location and can challenge high-risk attempts for additional verification.

Users can enrol multi-factor authentication with SMS or TOTP via an authenticator app. Tenants can require MFA for their users.

Tenants can federate with external identity providers via SAML 2.0 or OpenID Connect.

Application sessions follow Cognito’s token lifetimes. Access and ID tokens expire after 1 hour; refresh tokens after 30 days. After refresh-token expiry the user re-authenticates.

Authentication events are logged to Cognito’s event log. Account management actions are additionally captured in CloudTrail.

  • Amazon Aurora PostgreSQL is the primary data store for user-generated content.
  • Amazon DynamoDB holds transient data and data outside the primary platform flows: notifications, LTI nonces, and similar.
  • Amazon S3 stores content and media, served through Amazon CloudFront.

All are encrypted at rest using AWS KMS. See Configuration baselines for the full baseline.

Aurora uses both automated backups and AWS Backup. Automated backups run continuously with a 7-day retention window. AWS Backup adds a continuous recovery plan covering the last 8 days, plus scheduled snapshots: nightly copies retained 8 days in Sydney with a cross-region copy to Melbourne (8 days), weekly copies retained 32 days in both regions, and monthly copies retained 366 days with automatic transition to cold storage after one day.

DynamoDB point-in-time recovery is enabled on all production tables, covering any point in the last 35 days.

S3 user-content buckets have versioning enabled and replicate continuously to ap-southeast-4 (Melbourne) with a 15-minute RTO SLA.

A restore test is performed at least annually. The record is kept in Google Drive.

The platform has two long-lived environments:

  • Production, serving live user traffic in the Production AWS account.
  • Beta, used to validate changes before promotion to production, in the Development AWS account.

Ad-hoc environments may be provisioned for integration with customer systems, following Secure development.

Production and non-production environments live in separate AWS accounts, so production data is not reachable from non-production workloads. Customer data is never copied from Production into Beta or development; non-production environments hold seeded or synthetic data.

Compute scales automatically with load. AWS Lambda functions scale horizontally per invocation; ECS services (the transcription workers) scale on queue depth and scale to zero when idle. Aurora and DynamoDB scale read and write capacity within configured bounds.

Capacity alarms and SLO definitions are codified in Terraform alongside the resources they protect; routing into incident.io follows the service-prefix pattern described in Observability § Alarms.

System context:

LearnerEducatorChangineers PlatformLearning Management SystemInstitutional IdP (OIDC)TwilioSentryincident.io OIDC federation into Cognito LTI 1.3 + AGS 2.0Video callsError reportsAlerts and status page

Platform containers:

UserLMSInstitutional IdPTwilioChangineers PlatformCloudFrontAPI serverLTI grade syncCognitoAuroraDynamoDBS3MediaConvert + Transcribe HTTPSSign inLTI 1.3 launchVerify sessionOIDC federation (tenant-configured) Video callsEnqueue grade updatesAGS 2.0 scoreRecordings pipeline

Changineers integrates with Learning Management Systems (LMSs) using the LTI 1.3 specification, published by 1EdTech (formerly IMS Global). Changineers acts in the LTI Tool role; LMS products such as Moodle, Canvas, and Blackboard act in the Platform role.

Four services from LTI Advantage are in use:

  • 1. Core Launch (LTI 1.3), initiated by an administrator/instructor from the LMS to register Changineers as a tool on the course. The registration makes Changineers visible as a gradebook column and enables the SSO, NRPS and AGS services below.
  • 2. LTI SSO, which allows students to launch directly from the LMS into Changineers without a separate login step. The LMS acts as the trusted identity broker; see LTI SSO below.
  • 3. Names and Role Provisioning Services 2.0 (NRPS 2.0), which synchronises the course roster from the LMS at launch time so that users in Changineers correspond to the users in the LMS.
  • 4. Assignment and Grade Services 2.0 (AGS 2.0), which sends a learner’s score back to the LMS gradebook when they complete an activity in Changineers.

Both services are layered over open standards:

The integration exposes three endpoints on the Tool side:

  • POST /lti/login receives the OIDC login initiation from the LMS.
  • POST /lti/launch receives the signed id_token from the LMS and establishes a session.
  • GET /lti/jwks serves the Tool’s public keys so the LMS can verify tokens that Changineers signs.

Nonce replay protection is enforced for each launch; each id_token is signature-verified against the LMS’s JWKS, and state values are single-use.

LTI integration components:

LMSChangineers PlatformCloudFrontAPI server/lti/login, /lti/launch, /lti/jwksScore queue (SQS)LTI grade syncCognito(CUSTOM_AUTH)Aurora(registrations, resource links)DynamoDB(nonces, SSO challenges)SSM Parameter Store(Tool signing key) Instructor LTI 1.3 launchStudent LTI SSO launchPersist nonce / SSO challengeAdminInitiateAuth + AdminRespondToAuthChallenge (SSO)Upsert registration and resource linkRead Tool signing keyNRPS roster pull (OAuth 2.0 client credentials)Enqueue score on activity completionRead Tool signing keyAGS 2.0 score (OAuth 2.0 client credentials)

LTI launch and grade sync flow:

LMS (Platform)InstructorChangineers (Tool)Student Open Changineers tool from coursePOST /lti/login302 to LMS auth endpoint (state, nonce)POST /lti/launch (id_token + state)GET JWKS (verify signature)OAuth 2.0 client credentials (JWT bearer, RFC 7523)access_tokenGET context memberships (NRPS)rosterTool configuredComplete activity in ChangineersOAuth 2.0 client credentials (JWT bearer)access_tokenPOST /lineitems/{id}/scores

For tenants configured with LTI SSO, the LMS acts as the trusted identity broker. Changineers does not authenticate the user, it establishes a session based on LMS’s signed assertion.

End-to-end flow:

  1. User opens Moodle and authenticates via the institution’s IdP (e.g. Entra ID / Azure AD). Authentication completes before Changineers is involved.
  2. Authenticated user clicks the Changineers LTI link inside a course.
  3. Moodle constructs a signed LTI 1.3 OIDC launch payload containing the user’s opaque sub, role assertions, and LTI service callbacks.
  4. Browser is redirected to POST /lti/login. Changineers issues an OIDC authentication request back to Moodle (state + nonce).
  5. Moodle validates the correlation to the original user session and redirects the browser back to POST /lti/launch with a signed id_token.
  6. Changineers validates the launch: verifies the OIDC signature against Moodle’s JWKS, validates issuer, audience, nonce, state, and target_link_uri, then resolves the platform user via sub mapping or email fallback.
  7. Changineers establishes an internal application session and redirects the user to /app.
  8. Changineers syncs the course roster from Moodle via NRPS (system-to-system, token-scoped).
  9. On activity completion, Changineers submits grades to Moodle via AGS. Moodle remains the system of record.

Users must be provisioned before their first LTI launch. Setting ltiSso.lmsOnly on a tenant hides the platform login UI and shows an “Access via [LMS name]” prompt instead eg. “Access via UNSW Moodle”.

Institutional IdPUserMoodle (LMS)Changineers Open MoodleAuthenticateIdentity assertionClick Changineers LTI linkPOST /lti/login (browser redirect)302 OIDC auth request (state, nonce)POST /lti/launch (signed id_token)GET JWKS (verify signature)302 to /app (session established)NRPS roster sync (system-to-system)Complete activityAGS 2.0 score