Platform Evolution
Assessment run-2026-07-27-1 · 213 of 213 repos assessed
Repos / tc-mail-scheduler

tc-mail-scheduler

.NET 8 API and MassTransit consumers that schedule and send lifecycle customer emails (thank-you-for-booking, have-a-nice-time, welcome-home, TC-score reminders), triggered daily by an EventBridge Lambda.

100 · greenlowlooseAWSZDD: no excuseservice

Health score

100

0 to 100 across seven weighted factors; nothing is hidden. Green is 75 and above, amber 50 to 74, red below 50. How scoring works.


Runtime currency / 25
25
Runs on supported modern .NET
Legacy transport / 15
15
No legacy WCF or SOAP surface
Test posture / 15
15
Good test coverage
Security hygiene / 15
15
No credentials found in source
Dangerous coupling / 15
15
No dangerous coupling detected
Activity / 10
10
Actively maintained
Deployment hygiene / 5
5
CI in place
Health over time
2026-07-27 (run-2026-07-27-1): 100
Baseline 100 recorded 2026-07-27. The trend fills in with each monthly assessment run.

Facts

Languagescsharp, typescript
FrameworksASP.NET Core 8, MassTransit 8, MediatR, AWS Lambda
Runtimes.NET 8, nodejs 20
Tests / CIgood / CI in place
Last commit2026-06-01
OwnerOwner unknown (mapping to be curated)
DomainCustomer communications (system generated; curate in repo-owners.json to override)
Product areaShared platform
HostedAWS Deployed to AWS
  • build "tc-mail-scheduler" (azure-pipeline.yaml): AWS signal "ecsTerraformRepo"
  • build "tc-mail-scheduler-lambdas" (build-lambdas.yaml): AWS signal "useTFVarsDeployment: true"
Releases0 release pipeline(s):
Integrationrest, masstransit, sqs
SourceOpen in Azure DevOps

Risk flags

Each flag links to its glossary definition.

Dependencies in context

Laying out the graph…
greenamberreddata store (square, dashed link)Node size follows fan-in. Click any node to open it.

Entanglement

loose No binding mechanisms apply: this system needs no untangling work.

    Migration playbooks

    Generated from this repo's assessment data: what is feasible, what blocks it, and the steps in order. Ratings: green means actionable now, amber means sequence other work first, red means blocked, grey means not applicable.

    ZDD adoption

    No excuse

    Nothing technical is holding this repo on the three-week release. It either already deploys without downtime (AWS) or is a modern, well-tested service the automated stealth path can carry today. Already deploys as a container to AWS, which releases without downtime today. Separating it from the three-week release is a process decision, not a technical one.

    Dependencies and gotchas
    • 2 system(s) depend on this repo; during a rolling deploy they will talk to old and new versions at once, so responses must stay compatible
    • Serialized state or messages in flight (Redis or queues): new code must deserialize objects written by the previous version
    Steps
    1. Adopt the four-stage discipline from the ZDD engineering standard: pre-deployment compatibility, deployment, feature activation behind a flag, post-release cleanup.
    2. Make every change dual-version safe: backwards-compatible APIs (new major version for breaking wire changes), expand and contract for any schema change, and consumers tolerant of unknown fields.
    3. Audit serialized data: anything in Redis, queues or shared caches must deserialize cleanly across adjacent versions.
    4. Wrap behaviour changes in feature flags so code deploys dark and release becomes a business decision, not a deployment event.
    5. Use ECS rolling deployments with health checks gating traffic, and take this service off the three-week release train.
    6. Verify with area-scoped regression rather than the whole-platform cycle, and watch error rates after rollout with automated rollback on alert.

    SQL Server exit

    Not applicable

    No SQL Server dependency is recorded for this repo. Nothing to migrate.

    Containerisation

    Already containerised

    Its pipelines already build containers and deploy to AWS. Nothing to do here.

    Recommended actions

    No specific actions for this repo. It either needs only normal maintenance, or its work is covered by an estate-level action. See the full programme.

    Assessment notes

    tc-mail-scheduler

    Purpose

    Customer-experience (CX) mail scheduler: consumes contact, person-configuration, TC-score and transactional-email-activity events off the bus to build a MongoDB schedule of lifecycle emails per customer (thank-you-for-booking, have-a-nice-time, welcome-home, TC-score reminder — configured per company UK/IE/NL/BE/ZA/AE in appsettings), then sends batches via TC.Mail.Composer commands when a SendScheduledEmailsCommand arrives. A TypeScript Lambda (tc-mail-scheduler-send-scheduled-emails) is fired by EventBridge and publishes that command as a hand-rolled MassTransit envelope to an SNS topic.

    Tech stack

    C# on .NET 8 (API, Scheduler core, Abstractions, Contracts, Persistence, PublicTravelCounsellors client projects): MediatR, MassTransit 8.5 over TC.MassTransit.AmazonSQS, Mapster, FluentResults, FluentValidation, Polly, MongoDB.Driver 3.6 via TC.ConnectionBroker.Mongo, TC.Cognito.Auth.Client, Swashbuckle, Nerdbank.GitVersioning. The Lambda is TypeScript 4.9/webpack/Jest using the shared @tc/tc-aws-lambda-core package.

    Deployment

    No classic release pipelines (release_count 0) — deployment is YAML-only. azure-pipeline.yaml uses the shared InternalOSS/azure-pipelines-templates ci.yml (SDK 8.x), builds the TC.Mail.Scheduler.Api container (namespace cx) and deploys via Terraform tfvars into aws-cx-tc-apps ECS. build-lambdas.yaml builds/deploys the Node 20 Lambda to the tc-cx-function-artifacts bucket; deploy-mongodb.yaml runs TC.ScriptRunner.Mongo migrations. Build pipelines: tc-mail-scheduler, tc-mail-scheduler-lambdas.

    Dependencies

    Internal packages: TC.ConnectionBroker.* (tc-connectionbroker), TC.Mail.Composer.Contracts (tc-mail-composer, the send path), TC.Mail.Tracked.Contracts (tc-mail-tracked, transactional email activity events), Phenix.Contact.Contracts (phenix-contact-api, contact/person-configuration events), TC.Public.TravelCounsellors.Contracts plus an HTTP client to the public TC site API (tc-public-travelcounsellors, TC-score data), TC.Diagnostics.HealthChecks (tc-diagnostics-portal). External: AWS (SNS/SQS/EventBridge/Lambda/ECS), Cognito service auth.

    Data stores

    Owns the MailScheduler MongoDB database (scheduled emails, preferences, lease/batch state; migrations via Mongo script-runner). No SQL Server.

    Integration points

    Inbound REST (ScheduledEmails and ScheduledEmailPreferences controllers, Swagger); MassTransit over Amazon SQS/SNS for ten consumers (contact updated/deleted, person configuration, TC-score saved, transactional email activity, send/resend/create-custom commands); outbound send via mail-composer contracts.

    Code health

    Good: 208 xUnit facts/theories across API and core unit-test projects plus a shared fixtures project, coverlet coverage, analyzers (SonarAnalyzer, SecurityCodeScan, NetAnalyzers) enforced via Directory.Build.props. Jest configured for the Lambda (--passWithNoTests). Actively maintained (last commit 2026-06-01). README is untouched Azure DevOps boilerplate.

    Modernisation risks

    Low. Modern .NET 8 on ECS with YAML CI, tests and Mongo migrations. Residual concerns: the Lambda hand-crafts MassTransit message envelopes (mass-transit-message.ts), so envelope-format or contract-namespace drift would silently break scheduling; email-programme configuration lives in large per-environment appsettings blocks rather than data; boilerplate README.