Hotel PMS
A property management system for Italian hotels, built as microservices and documented honestly.
This showcase is under construction.
About this project
Hotel PMS is a microservices property management system for Italian hotels, designed and built solo, and actively maintained. This site documents it the way I'd want a codebase documented: real architecture decisions, a written threat model, enforced quality gates, and gaps stated openly instead of glossed over. If you're a recruiter, the code and the reasoning behind it are the point — start with the architecture and decisions below.
Questions about the project or a demo request for your hotel: diegoandruccioli@gmail.com
Architecture
Hotel PMS is built as 8 microservices behind a single API Gateway, plus one shared PDF-rendering library. The gateway is the only entry point: it validates JWTs, applies CORS and enforces Redis-backed rate limiting before a request reaches a service. Services never trust each other directly — every internal call carries an HMAC-SHA256 signature. Each stateful service owns its own PostgreSQL database, so there is no shared schema and no cross-service SQL join. Zipkin, Prometheus and Loki give distributed tracing, metrics and structured logs across the whole system.
Decisions and trade-offs
A few of the non-obvious choices made along the way, each with the alternative that was rejected and why.
- JWT in httpOnly cookies, not localStorage: the browser's JavaScript never sees the token, closing the classic XSS token-theft path.
- HMAC-SHA256 on every call between services, instead of mutual TLS: a compromised internal network still can't forge a request without the shared secret, without the cost of a certificate infrastructure.
- A hotel_id column on every entity, taken only from the verified JWT and never from client input, checked at build time by a dedicated test — a missing tenant filter fails CI, not production. Chosen over one database schema per hotel, which would cost far more to operate.
- A circuit breaker on every internal call: if one service is down, the rest keep working with partial data instead of the whole system going down with it.
- 8 services instead of a monolith, because billing, stays, guests and F&B each have a genuinely distinct data model and lifecycle — not because microservices are fashionable.
Security
Every JWT lives in an httpOnly cookie, so client-side JavaScript never sees it. Internal calls between services carry an HMAC-SHA256 signature, so a compromised internal network can't forge requests. Role-based access (admin, owner, receptionist) is enforced at both the gateway and the endpoint. Known accepted risks — like a Netty CVE mitigated by network isolation — are listed openly in the project's threat model, not hidden.
Quality and process
Every merge to main passes a zero-warning lint policy, an enforced coverage floor, end-to-end tests with automated accessibility checks, and a container image security scan — before it reaches production.
Measured 2026-08-04: 90.4% statement coverage on the frontend, 76.6% instruction coverage on the backend aggregate across 11 modules — both well above the floor the build enforces.
For hotels
Hotel PMS runs real operations, not just a demo: reservations, guest check-in and check-out, billing with charges posted straight from the restaurant, and the Italian compliance below.
Italian compliance, honestly
- Guest reporting to the Polizia di Stato (Alloggiati Web, TULPS art. 109): implemented, sent automatically at check-in.
- Electronic invoicing (FatturaPA, export validated against the official XSD schema): implemented. Direct transmission to the SDI exchange system is a deliberate choice not to build — see the compliance audit for why.
- Tourist tax (imposta di soggiorno): implemented, calculated and posted automatically at check-in.
- Electronic receipts for restaurant sales (corrispettivi telematici), mandatory by law since 2026-01-01: not built yet — an open gap, not a hidden one.
- GDPR: the right to erasure is implemented end to end; data export exists in the backend but has no button in the interface yet.
Status and roadmap
Already built
- Encrypted off-site backup (continuous WAL archiving), restore verified manually end to end.
- The hotel staff admin interface meets WCAG 2.2 AA.
- GDPR right to erasure: anonymisation that still respects the legal retention hold (TULPS, fiscal).
Not built yet
- Electronic receipts for restaurant sales, mandatory by law since 2026-01-01.
- A credit-note flow to correct an already-exported invoice.
- A channel manager connecting to OTAs — a prerequisite for most of the hotel market.
- A mobile app and an online booking engine with card payment.