PawSpace
The all-in-one platform connecting pet owners with products, services, adoption, and community.
The Challenge
The central engineering challenge was designing a single platform that meaningfully serves six distinct user roles — pet owners, vendors, vets, service providers, shelters, and admins — without collapsing into a monolith that is impossible to maintain. The tradeoff resolved by a Turborepo monorepo: shared packages (validators, utilities, database types) are consumed by both the Fastify API and the Next.js frontend, but the application layers are fully independent. This meant investing heavily in shared Zod schemas that double as runtime validators and TypeScript types. The domain itself is genuinely complex: 33 Prisma models with multi-directional relationships, cascading deletes, transactional order creation, availability slot computation for service providers, and snapshot pricing in order line items so historical orders do not corrupt when vendors update prices.
Architectural Decisions
Turborepo Monorepo with Shared Package Layer
A packages/shared layer houses all Zod schemas and utility functions consumed by both the Fastify API and the Next.js frontend. Turborepo provides task caching and parallel builds with zero config overhead.
Fastify Over Express for the API Layer
Fastify 5 was chosen over Express for its schema-based validation pipeline, native TypeScript support, and significantly higher throughput. It integrates cleanly with Zod via plugin hooks and ships with Swagger/OpenAPI generation out of the box.
Dual-Token JWT with Database Session Storage
Short-lived access tokens (15 min) paired with long-lived refresh tokens (7 days) stored in a Sessions table. This enables token revocation, user agent and IP tracking per session, and the ability to invalidate all sessions on password change.
Prisma with Strategic JSON Fields for Flexibility
The schema uses PostgreSQL natively via Prisma ORM, with JSON fields in targeted places: ProductVariant.attributes for arbitrary variant dimensions and OrderItem.variantInfo for historical price snapshots.
Transactional Order Checkout with Stock Decrement
Order creation runs inside a Prisma interactive transaction: validate cart items, check stock, create the order record, create line items with price snapshots, decrement product stock, and clear the cart — all atomically.
Argon2 for Password Hashing
Argon2id was chosen over bcrypt or PBKDF2 because it is the current OWASP recommendation and winner of the Password Hashing Competition. It is memory-hard, making GPU-accelerated brute force attacks significantly more expensive.