Availability & Calendar - Version Mapping
Shows which product versions use this domain and to what extent.
Version Matrix
| Version | Scope | Tables Used | Key Features | 
|---|---|---|---|
| MVP.0 | None | (not implemented) | Deferred - manual availability management only | 
| MVP.1 | Full | availability_calendars, blocks, holds, ical_feeds | Space-level calendars, GIST exclusion constraints, basic iCal export/import, advisory locks | 
| V1.0 | Full | +inventory_locks (explicit) | Unit-level calendars, explicit inventory locks, multiple export feeds, materialized views | 
| V1.1 | Full | +recurring_events, +vtimezone_cache | VFREEBUSY support, recurring events (RRULE), optimistic concurrency, partitioning, Redis cache | 
| V1.2 | Full | +bulk_operations, +occupancy_analytics | Bulk calendar operations, conflict detection UI, min/max stay enforcement, seasonal rules | 
| V2.0 | Full | +distributed_locks (Redis) | Multi-region replication, distributed locking, AI conflict resolution, cross-property aggregation | 
Changes by Version
MVP.0 - Not Implemented
Scope: None - Availability domain deferred to MVP.1.
Workaround:
- Manual blocking via admin UI creates placeholder records
- No automatic conflict detection
- No iCal synchronization
- No hold/quote workflow (direct to booking)
Rationale:
- Focus on core property setup and content first
- Availability complexity deferred to avoid delaying launch
- Manual calendar management sufficient for pilot customers
MVP.1 - Foundation (Space-Level Calendars)
Scope: Full implementation of availability management focused on single-unit spaces.
Tables:
- availability_calendars- Central calendar object per Space (one-to-one)
- blocks- Time ranges where Space/Unit unavailable (bookings, holds, owner blocks, maintenance, external events)
- holds- Temporary reservation locks (15-minute TTL) during quote-to-booking flow
- ical_feeds- Bidirectional iCal sync configuration (import/export)
Features:
- Space-level availability calendars (villa model: one calendar per Space)
- GIST exclusion constraints prevent overlapping blocks/holds (database-enforced)
- Block types: booked, hold, owner_block, maintenance, external, system
- Hold workflow with TTL expiration (default 15 minutes)
- Basic iCal export (public audience, confirmed bookings only)
- Basic iCal import with ETag optimization (HTTP 304 Not Modified support)
- PostgreSQL advisory locks for inventory locking during booking creation
- Availability check query function (optimized for speed)
- Hold expiration background job (runs every 60 seconds)
- Half-open interval notation [start, end)for time ranges
- UTC timestamp storage (timezone conversion at API layer)
Business Rules:
- Precedence hierarchy: Booking (confirmed) > Hold (active) > Block > Available
- GIST exclusion constraint THE CRITICAL DOUBLE-BOOKING PREVENTION mechanism
- Hold TTL default: 15 minutes (max 60 minutes)
- Lock TTL default: 30 seconds (max 5 minutes)
- Soft deletes for blocks (deleted_at column) for audit trail
- External events deduplicated by external_event_uid(iCal UID)
- Sync frequency default: 60 minutes (min 15 minutes)
- Import status → 'error' after 3 consecutive failures
Implementation Details:
- 4 tables (inventory_locks deferred to V1.0)
- 15+ indexes including GIST for range queries
- 10+ constraints including GIST exclusion for overlap prevention
- 2 background jobs: hold expiration, iCal sync
- Advisory locks via pg_advisory_lock()(session-level)
iCal Features:
- Export token security (bcrypt hash stored, never logged)
- ETag and Last-Modified headers for efficient sync
- RFC 5545 compliance (VCALENDAR, VEVENT components)
- External feed polling with conditional GET requests
Deferred to V1.0:
- Unit-level calendars (multi-room properties)
- Explicit InventoryLock table (using advisory locks in MVP.1)
- Multiple export feeds per calendar
- VFREEBUSY support
- Materialized availability views
- Advanced conflict resolution UI
- Bulk calendar operations
- Changeover rules and cleaning buffers
V1.0 - Unit-Level Calendars & Advanced Blocking
Scope: Full - Multi-unit property support with enhanced locking.
Changes from MVP.1:
- Unit-level calendar management (separate from Space)
- Aggregate availability at Space level (all units, partial units)
- Changeover rules engine (same-day turnover, cleaning buffers)
- Explicit InventoryLock table for observability
- Multiple export feeds per calendar (public, owner, partner)
- Materialized daily availability views for search performance
- Conflict resolution API endpoint with override capabilities
New Tables:
- inventory_locks- Explicit concurrency control (replaces advisory locks)
- changeover_rules- Configurable turnover policies per Space/Unit
- materialized_daily_availability- Precomputed availability snapshots (refreshed hourly)
Schema Changes:
- Add unit_idto availability_calendars table (nullable, one-to-one with units)
- Add XOR constraint: exactly one of space_id OR unit_id must be set
- Add buffer_hourscolumn to blocks table (cleaning/turnover time)
New Features:
- Unit-specific calendars for multi-room properties
- Space availability shows "2/5 units available" (aggregation logic)
- Changeover buffer enforcement (e.g., 4-hour cleaning between bookings)
- Same-day turnover rules (allow/disallow based on time)
- Explicit lock table enables lock monitoring dashboard
- Multiple iCal export audiences per calendar:
- Public: Only confirmed bookings (summary="Unavailable")
- Owner: Bookings + holds + owner blocks (detailed summaries)
- Partner: Bookings + partner blocks
 
- Materialized view for fast search queries (O(1) date range check)
- Conflict override API (admin can force booking despite conflicts)
Business Rules:
- One calendar per Unit (or per Space if single-unit)
- Changeover buffer applied automatically to end_at timestamp
- Materialized view refreshed hourly or on-demand via trigger
- Lock table entries expire if not released (cleanup job every 60s)
- Override bookings create audit log entry with justification
Performance:
- Search queries use materialized view (no live calendar computation)
- Lock table indexed by calendar_id and time range (GIST)
- Changeover rules cached in Redis (infrequent changes)
V1.1 - Advanced iCal & Performance
Scope: Full - RFC 5545 enhancements and optimization.
Changes from V1.0:
- VFREEBUSY endpoint for availability queries
- Recurring event support (RRULE parsing)
- VTIMEZONE component handling
- Optimistic concurrency control (version columns)
- Database partitioning by year for blocks table
- Redis caching layer for hot availability queries
- CDN distribution for public iCal feeds
New Tables:
- recurring_event_patterns- RRULE definitions and expansion cache
- vtimezone_cache- Parsed timezone definitions from external calendars
Schema Changes:
- Add versioncolumn to blocks table (optimistic locking)
- Partition blocks table by year (range partitioning on start_at)
- Add recurrence_rulecolumn to blocks table (RRULE string)
New Features:
- VFREEBUSY endpoint: GET /api/v1/ical/{token}/freebusy?start=X&end=Y
- Recurring block support (e.g., "Owner block every weekend")
- RRULE expansion engine (converts recurrence rules to explicit blocks)
- VTIMEZONE parsing from imported calendars (accurate timezone conversion)
- Optimistic locking prevents lost updates (compare-and-swap semantics)
- Blocks table partitioned by year (improves query performance, simplifies archival)
- Redis cache for availability checks (60-second TTL)
- CloudFront CDN for public iCal feeds (reduced origin load)
Business Rules:
- Recurring events expanded up to 2 years in advance
- RRULE expansion triggered on import or rule creation
- Optimistic lock failures trigger retry (max 3 attempts)
- Partitions created automatically at year boundary
- Redis cache invalidated on any block/hold change
- CDN cache TTL: 5 minutes (balance freshness vs. load)
Performance Improvements:
- Availability check (cached): <5ms (down from 10ms)
- Availability check (partitioned): <20ms (down from 50ms)
- VFREEBUSY query: <100ms for 1-year range
- iCal feed generation: <500ms for 1000 events
V1.2 - Operational Tools
Scope: Full - Bulk operations and analytics.
Changes from V1.1:
- Bulk calendar operations (block multiple units, date ranges)
- Calendar comparison/conflict detection UI
- Analytics: occupancy rate, booking lead time
- Min/max stay enforcement at database level
- Seasonal availability rules
- Dynamic pricing integration with availability
New Tables:
- bulk_operations- Audit trail for bulk calendar changes
- occupancy_analytics- Precomputed metrics (daily refresh)
- stay_duration_rules- Min/max night restrictions per Unit/date range
Schema Changes:
- Add min_nightsandmax_nightscolumns to blocks table (nullable, for available periods)
- Add seasonal_rule_idto availability_calendars table (link to recurring rules)
New Features:
- Bulk block creation (select multiple units, apply block to all)
- Bulk owner block management (e.g., "Block all units Dec 20-27 for maintenance")
- Calendar comparison view (side-by-side: Hostaway vs. TVL calendar)
- Conflict detection report (show discrepancies across channels)
- Occupancy analytics dashboard:
- Occupancy rate by month/quarter/year
- Average booking lead time
- Cancellation rate
- Revenue per available night (RevPAN)
 
- Min/max stay enforcement (database constraint validates booking duration)
- Seasonal rules (e.g., "7-night minimum June-August")
- Dynamic pricing integration:
- Pricing engine queries availability for demand-based pricing
- High occupancy triggers price increases (surge pricing)
- Low occupancy triggers discounts (gap-filling)
 
Business Rules:
- Bulk operations create audit log entries (who, what, when)
- Calendar conflicts highlighted in red (manual review required)
- Min/max night rules validated during booking creation
- Seasonal rules override default min/max settings
- Analytics refreshed daily (overnight batch job)
UI Enhancements:
- Drag-and-drop calendar blocking (select range, choose block type)
- Color-coded calendar view (booked=red, hold=yellow, owner=blue, maintenance=gray)
- Conflict resolution wizard (guide admin through discrepancy fixes)
V2.0 - Multi-Region & Advanced Features
Scope: Full - Enterprise-scale availability management.
Changes from V1.2:
- Multi-region database replication
- Distributed locking via Redis (replace PostgreSQL advisory locks)
- AI-powered conflict resolution
- Smart availability recommendations
- Cross-property availability aggregation
- Advanced analytics and forecasting
New Tables:
- distributed_locks- Redis-backed lock registry (replaces advisory locks)
- ai_conflict_resolutions- ML model decisions and overrides
- availability_forecasts- Predicted future occupancy (ML-generated)
Schema Changes:
- Add regioncolumn to availability_calendars table (data residency)
- Add replication_lag_mscolumn (monitor sync status across regions)
- Add ai_resolution_confidenceto blocks table (ML certainty score)
New Features:
- Multi-region availability (EU, US, APAC data centers)
- Redis-based distributed locks (fast, scalable, observable)
- AI conflict resolver:
- Analyzes historical booking patterns
- Suggests resolution for double-book scenarios
- Auto-resolves low-risk conflicts (high confidence)
- Escalates complex conflicts to human review
 
- Smart recommendations:
- "Your villa is blocked July 4-7. Based on demand, consider releasing it."
- "Competitor properties are 90% booked this month. Increase pricing?"
- "Gap between bookings too short for typical stays. Adjust min nights?"
 
- Cross-property availability search:
- "Show me all villas available Aug 10-17 in Tuscany"
- Aggregate availability across property networks
- Real-time inventory updates
 
- Forecasting:
- Predict occupancy 90 days out (ML model)
- Identify high-demand periods early
- Revenue optimization recommendations
 
Business Rules:
- Distributed locks expire after 30 seconds (same as advisory locks)
- AI resolutions require 95% confidence threshold for auto-apply
- Cross-region replication lag must be <100ms (alert if exceeded)
- Forecasts updated daily based on historical data + market trends
Performance:
- Distributed lock acquisition: <10ms
- Cross-region availability query: <200ms (eventual consistency)
- AI conflict resolution: <2 seconds
- Forecast generation: <5 seconds per property
Monitoring:
- Lock contention rate (high contention = bottleneck)
- Replication lag across regions (data freshness)
- AI resolution accuracy (track override rate)
- Forecast accuracy (compare predicted vs. actual occupancy)
Operational Notes
MVP.1 Performance Targets
- Availability check (cached): <10ms
- Availability check (cache miss): <50ms
- Hold creation: <150ms (includes lock acquisition)
- iCal export generation: <1 second (up to 1000 events)
- iCal import processing: <2 seconds (up to 1000 events)
Monitoring Requirements
- Track hold expiration rate (UX indicator: users abandoning quotes)
- Monitor GIST exclusion constraint violations (double-book attempts)
- Alert on iCal sync failures (channel out of sync)
- Track advisory lock wait times (contention indicator)
- Monitor hold conversion rate (hold → booking)
Background Jobs
- Expire Holds Job (every 60 seconds):
- Find holds with status='active' and expires_at < now()
- Update to status='expired'
- Delete associated blocks (soft delete)
 
- Import iCal Feeds Job (every 15 minutes):
- Find feeds with last_import_at < now() - sync_frequency
- Fetch external calendar with conditional headers
- Parse and upsert blocks
- Delete orphaned external events
 
- Cleanup Expired Locks Job (V1.0+, every 60 seconds):
- Find locks with released_at IS NULL and expires_at < now()
- Set released_at = now() (release lock)
 
Scaling Considerations
- Blocks table grows with booking volume (high write rate)
- Holds table is transient (aggressive TTL, frequent deletions)
- Availability_calendars table is relatively small (one per Space/Unit)
- GIST indexes are CPU-intensive (optimize for read performance)
- Consider read replicas for availability checks (read-heavy workload)
Backup & Retention
- Blocks retained indefinitely (soft delete only)
- Holds purged after 30 days (no business value post-expiration)
- iCal feeds retain import history for 90 days
- Advisory locks are session-based (no persistence needed)
Related Documents
- Domain Specification - Complete technical specification
- Schema Definition - PostgreSQL CREATE statements
- Supply Domain - Properties and Units
- Bookings Domain - Booking lifecycle
- Channels Domain - External distribution
- Deep Dive Report - Comprehensive analysis
- GIST Constraints Guide - Implementation patterns
- iCal RFC 5545 - iCalendar specification