Skip to content

Live events and ticketing · Case study

Paint Nite: Rebuilding a national events platform beside the legacy system

Event platform rebuild case study: a NestJS and Next.js replacement for Paint Nite's booking, checkout and operations, shipped in slices beside the old system.

Paint Nite product interface
Client
Paint Nite runs ticketed live events and experiences across the US and Canada.
Team
5 committing engineers alongside a client-side technical lead
Timeline
Database architecture from November 2025; platform development March to June 2026
Services
Enterprise software, Web development, Cloud and DevOps, AI and data
8
Backend services and 3 frontend apps
330+
Features across 49 modules
754
Automated test files run on every pull request
474
Data models across 3 databases

In short

Paint Nite needed a modern booking, checkout and operations platform but could not stop selling tickets while one was built. Five engineers delivered eight NestJS services behind one GraphQL gateway, three Next.js apps, a six-stage checkout with idempotent Stripe payments and zero-downtime search reindexing. Sync services keep the new platform aligned with the legacy one, so the migration ships in slices rather than a single switchover.

The challenge

Where they started.

  • A platform with more than a decade of change had become slow for customers and slow for the team building on it
  • The entire purchase flow lived in one function of roughly 1,200 lines, with no Stripe idempotency keys and a live double-charge risk
  • Adding a filterable field to event search required a manual reindex that took production search offline with no rollback
  • The business could not pause ticket sales while a replacement was built
What we did

The approach.

  • Eight independent NestJS services behind a single GraphQL gateway, communicating only through a RabbitMQ message queue
  • Checkout rebuilt as a six-stage pipeline: quote, tax, tender, persist, emit, effects, with an atomic order transaction and explicit compensation
  • Versioned OpenSearch indexes behind aliases, dual-write during rebuilds and resumable reindex jobs, so schema changes ship with no downtime
  • Dedicated sync services keep the new platform and the legacy one aligned, so features migrate in slices
  • A painting recommendation engine tuned over four measured iterations with an offline replay harness
  • Separate Stripe accounts, keys and webhook secrets for the US and Canada, with a Canadian tax path and per-state nexus rules
Deliverables

What shipped.

  • Public booking site with a country, state and city page hierarchy and seven types of structured data
  • Three-step checkout with idempotent payments, promo codes, membership join and zero-total orders
  • Internal operations console with 12 feature areas and 7 role-specific dashboards
  • Host management, payouts with PDF statements, venue management with Google Places enrichment
  • Private-event sales workflow with lead inbox, conversations and invoicing
  • Social media planning with AI-generated post suggestions and an approval flow
  • Shared design system with 12 UI primitives and centralised tokens
  • 26 architecture decision records and 42 feature documents
In detail

How the engagement ran.

Context

Paint Nite sells tickets to live painting events across the United States and Canada. The platform behind that business had grown for more than ten years and carried the marks of it: a 474-table database with backup and temporary tables, a purchase flow crammed into one very long function, and a search reindex process that could take production search offline halfway through with no way back. The team described the checkout code as a disastrous mess, and they were right to. The business needed a modern platform, but revenue depended on the old one every day.

The platform being replaced was not small. It had grown since 2014 into roughly 36 repositories and close to 29,600 commits, covering booking, a nine-processor checkout, tax handling in three countries, search, payouts and Kubernetes infrastructure. Any rebuild had to keep that system earning revenue every day while the new one took over slice by slice.

The engagement started with a database architecture phase in November 2025 and moved into active platform development from March to June 2026. Five engineers committed across two repositories and worked directly with a client-side technical lead.

What we built

  • A public site with homepage, event discovery, city landing pages, event detail, virtual and on-demand events, passes and membership, owner microsites and recruitment funnels
  • A rebuilt three-step checkout (review, pay, done) with promo validation, membership join, referral cards and a zero-total path
  • An order pipeline in six replaceable stages: deterministic decimal pricing, tax behind a swappable provider, multi-method tender, atomic persistence, publishing to the message bus, and queued effects
  • An operations console with 12 feature areas: event draft generation, calendar management, host management and payouts, venue management, painting catalogue, private-event sales, social planning and owner administration
  • A painting recommendation engine with tag-based selection, signal tables, a venue no-repeat rule and lottery sampling
  • A GraphQL gateway with 88 queries and 80 mutations across 27 resolvers, request throttling and structured logging with trace propagation
  • Search, notification, event, venue, user, media, AI and legacy-sync services

Architecture and stack

LayerTechnologyWhy
FrontendNext.js, React 19 with the React Compiler, TypeScript, Turborepo, Tailwind, Zustand, Apollo ClientThree apps share one component library and one GraphQL client setup
GatewayNestJS, Apollo Server GraphQLAuthentication, rate limiting and logging happen once, at one entry point
ServicesEight NestJS microservices, RabbitMQ, Zod, PinoServices own their tables and talk only through the queue, so cross-domain shortcuts are impossible by construction
DataMySQL across three databases, Prisma with per-domain clients, OpenSearch, Redis/ValkeyCore, operations and accounting data stay separate; search never touches transactional tables
InfrastructureAWS object storage, managed OpenSearch and message broker, DynamoDB, Lambda, EventBridgeManaged services keep the operations burden low for a five-person team
IntegrationsStripe (US and Canada), Auth0, Twilio, Mandrill, Iterable, Google Places, Anthropic, fal.ai, TalkJS, Google Tag ManagerPayments, identity, messaging and AI features without building commodity pieces

Checkout originally lived inside the events service. It was pulled into its own service so that a bad deploy in event management could never take payments offline, and payment credentials now exist in exactly one place. Tax sits behind an interface so the real provider can be swapped without touching pricing, and payment is a multi-method abstraction from the start, so gift cards and passes become new processors rather than new branches.

How we worked

Everything in the process is visible in the repositories rather than described in a slide. Tests run on every pull request through Bitbucket Pipelines in both repositories: 158 backend test files, 589 frontend test files and 7 end-to-end browser specs, with a written policy of 80 percent coverage on new code and 95 percent on checkout and authentication. Main and develop are protected, all code enters through reviewed pull requests, and automated review runs alongside the human one.

Decisions are written down. The team produced 26 architecture decision records, each listing the alternatives considered and the trade-offs accepted, 42 plain-English feature documents and 8 design plans. A defined security audit runs before any pull request touching authentication, payments, user input or a new integration. Every schema change ships as a reviewed migration and production takes a snapshot before each one.

Scale and complexity

MeasureFigure
Backend services / frontend apps8 / 3
Modules / features49 / 330+
GraphQL operations168 (88 queries, 80 mutations)
Internal service handlers188
Data models / databases / migrations474 / 3 / 53
Automated test files754
Architecture decision records26
The hardest problem was not the code volume but the recommendation engine. A replay harness built to test the algorithm against historical events caught it choosing the same painting 187 times out of 187, a failure that would have been invisible in production until every event looked identical.

What this means for your project

If you run a revenue-critical platform that has outgrown its codebase, the pattern here is the one to copy: put a single gateway in front, split the riskiest flow into its own service, and keep the old system alive with sync services while features move across one at a time. The cost of that discipline is a few extra weeks of architecture. The payoff is that no release day is a bet on the whole business.

Innovation Insight delivers rebuilds like this with a dedicated team on a monthly contract, with discovery first so the scope and estimate are written down before the first sprint.

Outcome

What changed.

  • Search schema changes that previously required production downtime now ship with none
  • Checkout runs with idempotent payments, atomic order persistence and queued, retryable side effects
  • The replay harness caught the recommendation algorithm selecting the same artwork 187 times out of 187 before it reached production
  • 168 GraphQL operations and 188 internal service handlers delivered, with 53 tracked migrations
FAQ

Questions about this project.

Can you rebuild our platform without taking it offline?

Yes. This project ran the new platform beside the legacy one with dedicated sync services, so features moved over in slices. The same approach applies to most replatforming work: keep the old system serving traffic and migrate module by module.

How do you keep payments safe during a checkout rewrite?

Every charge carries an idempotency key, database writes run in a transaction, and the card charge sits outside it with explicit rollback. Side effects such as emails and CRM sync go onto a queue with retries and a dead-letter queue.

What does a build like this cost?

Multi-service platforms of this size run from $150k upward and are usually delivered by a dedicated team over four to eight months. A one to two week discovery gives you a fixed estimate for your scope.