Case study
PlayPadel
Operations platform for a padel club
- Client
- Padel club (Italy)
- Duration
- Ongoing since 2024
- Role
- Sole engineer: architecture through operations
The problem
The club ran bookings through Playtomic, communications through WhatsApp, and match organisation through spreadsheets and memory. Staff spent hours reconciling court availability, chasing no-shows, and manually notifying players about schedule changes.
Constraints
- Playtomic's API is the source of truth for court bookings: the system must sync, not replace.
- Players expect WhatsApp messages, not emails, and delivery must be reliable and traceable.
- Single VPS budget: no Kubernetes, no managed queue service, no room for operational complexity.
- Real player data in production: GDPR compliance and PII scrubbing are non-negotiable.
What we built
A full-stack operations platform: admin panel for staff, automated Playtomic sync, WhatsApp notification pipeline, match management, and reporting, deployed as Docker containers on a single VPS with automated rollback.
Architecture
Hexagonal (ports and adapters) architecture keeps domain logic isolated from infrastructure concerns.
- Domain layer: booking rules, match lifecycle, notification policies. Pure TypeScript, zero framework imports.
- Application layer: use cases orchestrate domain services through defined ports.
- Infrastructure adapters: Playtomic REST client, Twilio WhatsApp sender, Prisma repositories, Sentry error reporting.
- Presentation layer: Next.js admin UI with server components and typed API routes.
Playtomic integration
Scheduled sync jobs pull court availability and reservations from Playtomic's API. Conflicts are detected at the domain level and surfaced to staff before they become double-bookings. The adapter handles rate limits, pagination, and API version drift behind a stable port interface.
WhatsApp / Twilio outbox
Outbound messages go through a transactional outbox: the domain event is persisted first, then a background worker delivers via Twilio's WhatsApp API. Failed sends retry with exponential backoff; permanent failures are logged and surfaced in the admin panel. No message is lost because the HTTP call failed.
Data layer
PostgreSQL with Prisma ORM. Migrations are version-controlled and applied in CI before deploy. Schema changes follow expand-contract pattern to avoid downtime on the single-instance database.
Infrastructure & rollback
Docker Compose on a single VPS. GitHub Actions builds and pushes images to GHCR; deploy script pulls, runs health checks, and automatically rolls back to the previous image if the new container fails to start. Observed rollback time: under 60 seconds.
Observability
Sentry for error tracking with PII scrubbing configured at the SDK level: names, phone numbers, and message bodies are stripped before events leave the server. Structured logging for integration failures; no personal data in log lines.
Results
- Staff time on manual booking reconciliation reduced from hours daily to minutes weekly.
- WhatsApp delivery rate above 99% with full audit trail via the outbox table.
- Zero unplanned downtime from bad deploys since rollback automation shipped.
- Platform handles peak booking volume (weekend mornings) without manual intervention.
Stack
TypeScript · Node.js · Next.js · PostgreSQL · Prisma · Docker · GitHub Actions · Twilio · Sentry · Cloudflare
Want a walkthrough of the admin panel? Get in touch and we'll show you the interesting parts.
Request a walkthrough