In this volume · VOLUME 00
Introduction
Platform Overview System Architecture Glossary Technology Stack

Chapter 0.4 — Technology Stack

1. Purpose

This chapter inventories every technology in travoBooks' production stack: language runtimes, frameworks, datastores, infrastructure components, libraries, observability tooling, and supporting services. It serves as the canonical reference for new engineers, security reviewers, vendor due-diligence, and operations runbooks. When a chapter elsewhere references "the cache layer" or "the queue worker", the concrete component is defined here.

2. Why it matters in modern travel accounting

Travel-accounting platforms are unusual: they combine high-volume transactional workloads (booking inserts at airline-network latency), strict financial integrity (double-entry posting must not lose a single line), and integrations with legacy XML-heavy systems (GDS, BSP, IATA portals). Stack choices are constrained by these forces — for example, the operational database and ledger must share a single ACID transaction for issuance to be safe, which is why the platform uses a relational RDBMS rather than a polyglot persistence layer.

3. Industry relevance

The stack favours boring, well-understood components over novelty. Auditors recognise MySQL and standard SQL; insurers and banking partners ask familiar questions about TLS, KMS, and DR; engineers can join the team without learning bespoke languages. Travel-tech specifically benefits from PHP's mature SOAP / XML tooling — necessary for Amadeus, Sabre, and Travelport legacy endpoints — without forcing the platform onto an obscure runtime.

4. Compliance considerations

  • PCI DSS — payment card data never lands in the application DB; gateway tokens only. The stack section on cardholder-data boundary is enforced at the integration layer (see Volume 7).
  • GDPR / data-protection — encryption at rest (AES-256 on EBS/S3/RDS), encryption in transit (TLS 1.2+ exclusively), key custody via cloud KMS with rotation.
  • SOC 2 / ISO 27001 readiness — every stack component emits structured logs to a central WORM-retained log store; immutable audit trail is preserved for ≥7 years.
  • IFRS 15 / IAS 21 enforcement at code level — the JE engine is the only path from operational state to the ledger; the stack does not expose direct SQL writes to the GL.

5. Stack inventory

5.1 Application runtime

Component Version baseline Role
PHP 8.2 LTS (8.3 supported) Primary application language
OPcache Bundled Bytecode caching
JIT Enabled (tracing mode) Hot-path performance
Composer 2.7+ Dependency management
PHP-FPM Bundled Process manager behind Nginx

PHP was chosen because (a) the founding team has deep PHP expertise, (b) the Amadeus / Sabre SOAP toolchain is mature in PHP, (c) hosting costs are low, and (d) the codebase already runs cleanly on PHP 8+ with strict types. Future hot paths may be extracted to compiled services but the monolith remains PHP.

5.2 Web tier

Component Version Role
Nginx 1.24+ Reverse proxy, TLS termination, static asset serving, rate-limiting
HTTP/2 Enabled Multiplexed client connections
Let's Encrypt / ACM Auto-renew Certificate management
ModSecurity (CRS 4) Enabled in detect mode WAF — moves to block mode for known attack patterns

.htaccess style URL hiding (per platform UX preferences) is implemented by Nginx try_files rules; .php extensions never appear in client-facing URLs.

5.3 Database tier

Component Version Role
MySQL 8.0 LTS (MariaDB 10.11+ compatible) Primary OLTP store — all operational + ledger data
InnoDB Default engine ACID, row-level locking, foreign keys
Read replicas 2× minimum in prod Reporting, search, read-heavy endpoints
MyDumper / mysqldump Nightly Logical backups
Percona XtraBackup Hourly incremental Physical backups for fast restore

travoBooks uses a single primary database for operational + financial data. This is deliberate: it guarantees that booking issuance and journal-entry posting occur in one transaction, removing the entire class of "ledger drift" bugs that plague distributed-database designs in travel.

5.4 Cache & queue

Component Version Role
Redis 7.2+ Session store, permission cache, distributed locks, queue backend, idempotency-key store
Sentinel / Cluster Enabled in prod HA failover
Queue framework Internal travoBooks\Queue (Redis-backed) Async jobs — emails, GDS polling, webhooks, BSP imports
Cron orchestrator Single elected leader (Redis lock) Scheduled jobs (FX refresh, BSP import, dunning)

5.5 Object storage

Component Role
Amazon S3 (or compatible — MinIO, Wasabi) Documents — invoices PDF, receipts, BSP reports, supplier statements, KYC files
Bucket-per-partner logical layout travobooks-docs-prod/<partner_id>/<year>/<month>/<doc_id>.<ext>
Bucket policies Deny public read; presigned URLs only
Server-side encryption SSE-KMS with per-partner key alias
Component Role
MySQL FULLTEXT indexes Phase 1 search across customers, suppliers, bookings, invoices
OpenSearch / Elasticsearch Phase 2 (planned) — high-volume cross-module search

5.7 Email & messaging

Component Role
AWS SES Transactional email (invoices, receipts, alerts)
PHPMailer SMTP client library
Twilio / Local SMS gateways OTP, critical alerts
Webhook delivery service Internal — signed HTTPS POST with retries

5.8 Frontend

Component Role
Server-rendered HTML (PHP templates) Primary UI — fast, indexable, simple
Tailwind CSS (custom build) Styling, brand colour #C7090C
Sora / Inter / JetBrains Mono Typography
Lucide icons Iconography
Vanilla JS + light Alpine.js Interactivity; no SPA framework
HTMX (selective) Partial-page updates for high-interaction screens (booking, JE entry)

The UI uses a server-rendered, progressive-enhancement model — chosen for predictability, accessibility, low operational overhead, and because financial UIs benefit from the simplicity of submit-and-redirect patterns.

5.9 Integrations layer

Integration Library / SDK
Amadeus GDS Custom IttAMASearch + SOAP client; XML parsing via DOMDocument / SimpleXMLElement
Sabre GDS REST client (Sabre OAuth2)
NDC offers REST clients per supplier (IATA NDC Level 3 schemas)
LCC aggregators REST — per aggregator schema
Hotel suppliers (Hotelbeds, etc.) REST clients
Payment gateways Stripe SDK, regional gateway SDKs (SSLCommerz, Razorpay, etc.)
BSP / ARC SFTP polling + parsing of HOT, AGTDATA, BSPLink CSV files
Accounting export QuickBooks IIF, Xero CSV, Tally XML (Phase 2)

5.10 Observability

Component Role
Structured JSON logs Every request logged with request_id, partner_id, user_id, route, duration_ms, status
OpenTelemetry Traces across HTTP / DB / Redis / queue
Prometheus + Grafana Metrics dashboards
Sentry (self-hosted Glitchtip option) Error aggregation
Uptime checks Synthetic monitoring on critical endpoints
Audit log (DB-backed) Business-event log — separate from operational logs, retained ≥7 years

5.11 Security stack

Component Role
Argon2id Password hashing, PAT hashing
TOTP (RFC 6238) Multi-factor authentication
WebAuthn Phase 2 — passkey support
CSP (Content-Security-Policy) Strict; no inline scripts in production builds
Cookie flags HttpOnly, Secure, SameSite=Strict, __Host- prefix
CSRF tokens Per-session, per-form rotating tokens
Rate limiting Nginx layer + application layer (Redis sliding window)
WAF ModSecurity CRS 4
Secrets manager AWS Secrets Manager / HashiCorp Vault
KMS AWS KMS or compatible; key rotation enforced

5.12 Infrastructure

Component Role
Cloud provider AWS primary; portable to GCP / Azure / on-prem
VPC layout Public subnets (LB only), private subnets (app + DB), no public DB exposure
Application servers 2× minimum behind ALB
Database RDS / managed MySQL (or self-managed with Percona)
Bastion / SSM Session Manager for ops access; no inbound SSH
CI/CD GitHub Actions → ECR / artifact store → blue-green deploy
IaC Terraform (preferred) or CloudFormation

6. Module dependencies

The technology stack is the substrate for every module in the platform. No module bypasses these layers — direct database access from controllers is forbidden; all DB writes go through the persistence layer (see Volume 1), and all ledger writes go through the JE engine (see Volume 5).

flowchart TB UI[PHP Templates + Tailwind] --> APP[PHP Application Layer] APIClient[External API Client] --> APP APP --> CACHE[Redis Cache] APP --> DB[(MySQL Primary)] APP --> QUEUE[Redis Queue] QUEUE --> WORKERS[PHP Workers] WORKERS --> DB WORKERS --> S3[S3 Object Store] WORKERS --> SES[AWS SES] WORKERS --> GDS[GDS / NDC / LCC APIs] DB --> REPLICA[(Read Replica)] REPORTING[Reporting UI] --> REPLICA OBS[OpenTelemetry / Prometheus] -.-> APP OBS -.-> WORKERS OBS -.-> DB

7. Security & permissions

Every stack component runs with least privilege. The application database user has DML on operational tables but no DDL; schema changes go through a separate migration user. The cache and queue Redis instances are isolated network-wise from public ingress. S3 buckets are private with KMS-managed encryption; access is scoped per partner via prefix-based IAM policies in Phase 2.

8. Validation rules (deployment checklist)

Code Rule
STACK_TLS_VERSION_BELOW_1_2 TLS version below 1.2 detected — deploy blocked
STACK_DB_PUBLIC_EXPOSURE DB instance reachable from public subnet — deploy blocked
STACK_KMS_KEY_ROTATION_DISABLED KMS key rotation not enabled — deploy blocked
STACK_BACKUP_OLDER_THAN_24H No successful backup in 24h — paging alert
STACK_REPLICA_LAG_OVER_60S Read replica lag > 60s — paging alert

9. Common pitfalls (⚠️)

  • ⚠️ Do not introduce a second OLTP database. Any "side store" that holds financial state becomes a reconciliation problem. Side stores are acceptable only for read-only projections (search, analytics, cache).
  • ⚠️ Do not write to the ledger outside the JE engine. SQL INSERT INTO journal_entries from a controller is a serious bug — bypasses balance check, dimension validation, period state, FX capture.
  • ⚠️ Do not bypass the queue for slow integrations. Synchronous GDS calls inside a request can exceed timeouts; always queue-and-poll for long-running supplier operations.
  • 🔒 PCI scope. PAN data must never enter the application database. If a feature appears to require storing PAN, route through the gateway tokenisation flow instead.

10. Future scalability

  • Phase 2 — extract the read-heavy reporting layer to OpenSearch + materialised views on the replica.
  • Phase 3 — move BSP / supplier-import workers to a separate cluster (Kubernetes-managed) for elastic batch scaling.
  • Phase 4 — partner-id-based sharding of the primary DB when a single partner approaches 5M bookings/year or the total transaction volume exceeds the headroom of vertical scaling.
  • Phase 5 — optional read-only GraphQL layer for partner-built dashboards.

The stack does not plan to migrate languages or break the monolith for the sake of architectural fashion. Changes are driven by measured limits, not by trend.