Holibob Docs

Architecture

Internal architecture of the GraphQL API layer.

Layered architecture

The GraphQL API follows a layered design where each layer has a clear responsibility:

Apollo Server (HTTP + WebSocket)
        │
        ▼
Schema Layer (Queries, Mutations, Types, Resolvers)
        │
        ▼
Service Layer (Business logic)
        │
        ▼
Facade Layer (Cross-service orchestration)
        │
        ▼
Repository Layer (Data access)
        │
        ▼
Data Sources (RDS via Knex, Athena, Redis, External APIs)

Schema layer

Located in graphql-api/lib/schema/, this layer defines the GraphQL schema programmatically using graphql-js and graphql-compose.

DirectoryPurpose
queries/Query field definitions
mutations/Mutation field definitions
resolvers/Resolver implementations
types/GraphQL object and input type definitions
dataloaders/DataLoader factories for batch loading
fields/Reusable field definitions
internal/Internal-only queries (not exposed externally)
queriesPrivate/Private queries for internal services

The root schema is assembled in schema/index.ts using GraphQLSchema with query and mutation root types.

Context

Every request creates a GraphQLContext object (schema/GraphQLContext.ts) that contains:

  • Database connections — Knex RDS client and Athena client for analytics
  • Redis client — for caching and pub/sub
  • Services — instantiated per-request business logic services
  • Principal — the authenticated user or API key identity
  • Access control — permission checks
  • DataLoaders — per-request DataLoader instances for batch loading
  • Request metadata — unique request ID, headers, IP address

Context is created via schema/createContext/ and passed to every resolver.

Service layer

Located in graphql-api/lib/services/, this layer encapsulates business logic. Services are instantiated per request and injected via the GraphQL context. Key services include:

  • Distribution channel management
  • Product content and pricing
  • Booking lifecycle
  • Consumer trip orchestration
  • Payment processing
  • Entity management
  • Search and filtering

Facade layer

Located in graphql-api/lib/facades/, facades coordinate complex operations that span multiple services. They provide a single entry point for multi-step workflows.

Repository layer

Located in graphql-api/lib/repositories/, repositories handle data access using Knex query builder against PostgreSQL (RDS). Each repository is responsible for a specific domain entity.

Plugin architecture

Apollo Server plugins are defined in graphql-api/lib/plugins/:

PluginPurpose
cloudwatchMetricsPluginCloudWatch performance metrics
datadogPluginDatadog APM integration
sentryPerformanceMetricsSentry error and performance tracking
createErrorHandlerPluginStandardised error formatting
loggerPluginRequest and operation logging

Server entry points

The API supports two deployment modes:

  • Express server (graphql-api/server.ts) — for local development and traditional deployments
  • AWS Lambda handler (@as-integrations/aws-lambda) — for serverless deployments

Both share the same schema and context creation logic.