// Case study · N°01
CoraVet.
Multi-tenant veterinary SaaS, sole engineer, live in production.
- Role
- Founder · Full-stack
- Year
- 2025 → now
- Status
- live
- Stack
- NestJS 11 · Prisma 7 · PostgreSQL
A multi-tenant veterinary clinic SaaS I designed, built, and operate end-to-end as the sole engineer, from the data model and API through the dashboard, infrastructure, security hardening, observability, and go-to-market. The first live tenant is a real clinic in La Concordia, Ecuador.

// Context
The Ecuadorian SMB veterinary market is tech-skeptical, so the product is deliberately positioned as "your own clinic online": each clinic gets a personalized site and URL, not a seat on a shared platform. Regulated electronic invoicing was intentionally left out of scope; it belongs in the clinic's existing accounting tool.
Team
Sole engineer
Status
Live production tenant
Schema
26 Prisma migrations
Hardening
11-layer prod defense
What it is .
Two product surfaces from one codebase: a public marketing site plus per-clinic customer portal (Astro, statically rendered to Cloudflare), and an operational dashboard SPA for vets, managers, and staff (Vite + React 19). Both sit on a NestJS 11 API with a multi-tenant Prisma schema on PostgreSQL (Neon), organized as a pnpm + Turborepo monorepo with shared UI, API-client, and type packages.
Engineering depth .
Security and correctness are designed in, not bolted on.
- Three stacked NestJS guards: Firebase auth, role, and a legal-acceptance gate that returns a machine-readable 403 the SPA routes on.
- A Server-Sent Events layer (30+ typed events, per-user/clinic/role scoped) whose 30s heartbeat re-verifies Firebase session revocation in-band, closing stale streams within 30 seconds of deactivating a user.
- Timezone correctness via a dedicated date-utils module: all datetimes UTC timestamptz, all query boundaries clinic-local; a documented invariant after a near-miss.
- LOPDP-compliant legal versioning: SHA-256-hashed canonical Markdown, append-only acceptance table, boot-time drift detection, right-to-erasure as anonymization.
- Server-side image pipeline (Sharp → WebP @ q80) turning multi-MB phone photos into ~80 KB cards, plus client-side pre-compression.
Infrastructure & operations .
A DigitalOcean droplet behind Cloudflare (WAF, Origin Cert, R2), with public SSH eliminated entirely. Both personal and CI/CD access ride a Tailscale private mesh. A multi-stage Alpine Docker image runs non-root with memory/CPU caps; a single GitHub Actions pipeline deploys from git push in under four minutes. Structured Pino logs with request-id propagation and free-tier-safe Sentry give end-to-end traceability.
Beyond the code .
I owned the launch, not just the build: brand and positioning decisions, LOPDP-compliant legal docs, and a 7,400+ entity Ecuador veterinary prospect dataset merged from five public sources (vet directories, Agrocalidad, Google Places, the SRI RUC catastro, OpenStreetMap) with a self-served filtering dashboard. Built with Claude Code as a pair-programming assistant throughout.
Notable decisions.
SSE over WebSockets
Real-time is one-way here. SSE rides standard HTTP/2, plays nicely with Cloudflare and firebase-admin-verified session cookies, and needs no custom auth handshake.
Cloudflare Origin Cert + IP-only firewall over Let’s Encrypt
A 15-year cert with no renewal failure mode, and a Cloudflare-IP-only droplet firewall that makes a leaked origin cert near-irrelevant.