Travelopia

MyTCS performance · Tech Lead · Oct 2023 — Present · 1 min read

Cut page load from 12s to under 400ms for three luxury brands.

Internal tool
MyTCS login, TCS World Travel brand
Page load
12s → 400ms
Brands, 1 codebase
3
Teams managed
2

The problem

MyTCS is the post-booking portal for TCS World Travel, Smithsonian Journeys and Four Seasons. Salesforce is the source of truth, and every page waited on it.

What we did

  • Put a Redis getOrSet cache in front of Salesforce queries.
  • Moved slow operations onto SQS FIFO queues so pages stopped waiting on them.
  • Lazy-loaded components, prefetched images and split CSS per route.

Key decisions

  1. 01

    Redis getOrSet cache in front of Salesforce

    Trade-off: Accepted brief staleness on cached reads in exchange for sub-second pages.

  2. 02

    SQS FIFO queues for async operations

    Trade-off: Writes became eventually consistent; ordering was kept over raw throughput.

  3. 03

    Semantic token theming for three brands

    Trade-off: More upfront token design instead of maintaining per-brand forks.

  4. 04

    Lazy-loading and code-splitting

    Trade-off: Small extra requests on navigation for a much faster first load.

Architecture

React 18 appAuth0Sanity CMSNestJS + tRPCRedis cacheSalesforceSQS FIFOPostgreSQLDatadog

Hover or tab through the components to trace the data path.

  • React 18 app — One codebase, three brand themes
  • Auth0 — JWT login, Traveller and Assistant roles
  • Sanity CMS — Trip content
  • NestJS + tRPC — 15+ domain routers, Zod-validated
  • Redis cache — getOrSet in front of Salesforce
  • Salesforce — Source of truth for bookings
  • SQS FIFO — Async operations, ordered
  • PostgreSQL — Prisma schema, permissions, audit trails
  • Datadog — Distributed tracing

Screenshots

  • MyTCS dashboard, Four Seasons brand

  • MyTCS destination page, Smithsonian Journeys brand

Result

Page load dropped from 12s to under 400ms, on one codebase serving three brands.

What I learned

  1. 01

    Measure where time goes before optimising: the wait was on Salesforce, not React.

  2. 02

    A cache in front of a system of record needs an agreed staleness budget with the business.

Stack

  • React 18
  • TypeScript
  • tRPC
  • NestJS
  • Redis
  • AWS SQS
  • Prisma
  • PostgreSQL
  • Auth0
  • Datadog

Want something like this for your business?