Skip to main content

Architecture Overview

GitGazer is a serverless application built on AWS that monitors GitHub Actions workflows in real time. It receives webhook events from GitHub, processes them asynchronously, stores them in a PostgreSQL database, and pushes live updates to connected clients.

System Diagram

Request Flow

  1. Webhook ingress — GitHub sends webhook events to API Gateway. The REST Lambda validates the HMAC signature and enqueues the event to an SQS FIFO queue.
  2. Async processing — The Worker Lambda consumes events from SQS, inserts/upserts data into Aurora PostgreSQL, and triggers side effects (WebSocket push, alerting).
  3. Real-time updates — The Worker pushes workflow updates to connected WebSocket clients via the API Gateway Management API.
  4. Frontend — The Vue 3 SPA is served from S3 via CloudFront. It communicates with the REST API over HTTPS and receives live updates over WebSocket.
  5. Authentication — Users sign in via GitHub OAuth through AWS Cognito. Session tokens are stored in httpOnly cookies.

Monorepo Structure

GitGazer is a pnpm monorepo with the following workspaces:

WorkspacePurposeTech Stack
apps/api/AWS Lambda backend — REST API, WebSocket handler, worker, alertingTypeScript, Node.js 24, Drizzle ORM
apps/web/Single-page application frontendVue 3, Radix Vue, Tailwind CSS 4, Pinia, Vite
apps/docs/Documentation site (this site)Docusaurus
packages/db/Shared database schema, types, and clientDrizzle ORM, TypeScript
packages/import/Historical GitHub Actions data backfill utilityTypeScript
infra/Infrastructure as codeTerraform, AWS

Key Technology Choices

AWS Lambda (Serverless Compute)

All backend logic runs on AWS Lambda — REST API handler, WebSocket handler, webhook worker, and scheduled org sync. This means zero idle cost, automatic scaling, and no server management.

Aurora PostgreSQL Serverless (Database)

The database is Aurora PostgreSQL Serverless v2 with an optional RDS Proxy for connection pooling. Row-level security (RLS) enforces tenant isolation at the database level — every query runs within a transaction scoped to the user's integrations.

Drizzle ORM (Database Access)

Drizzle provides type-safe database access with a lightweight footprint suitable for Lambda cold starts. It handles migrations via drizzle-kit and generates TypeScript types from the schema.

Vue 3 + Radix Vue (Frontend)

The SPA uses Vue 3 with the Composition API (<script setup> syntax). UI primitives come from Radix Vue for accessibility. Styling uses Tailwind CSS 4. State management uses Pinia.

Terraform (Infrastructure)

All AWS resources are defined as Terraform HCL files in infra/. This enables repeatable deployments, change previews via terraform plan, and version-controlled infrastructure.

Infrastructure alerting and monitoring configuration is documented in Infrastructure Monitoring & Alerting.

Lambda Functions

GitGazer deploys multiple Lambda functions, each with a distinct responsibility:

LambdaTriggerPurpose
REST APIAPI Gateway HTTPHandles all REST API requests (auth, integrations, workflows, notifications, etc.)
WebSocketAPI Gateway WebSocketManages $connect and $disconnect lifecycle events
WorkerSQS event sourceProcesses webhook events asynchronously — inserts data, pushes WebSocket updates, sends alerts
Org SyncEventBridge schedulePeriodically syncs GitHub organization members to integration memberships
HTTP ProxyLambda invoke (internal)Optional outbound proxy for IPv4-only upstreams (for example GitHub and Slack)

Database Connectivity (Optional RDS Proxy)

Lambda functions connect to Aurora PostgreSQL using IAM authentication. An RDS Proxy can optionally sit between Lambda and Aurora to provide connection pooling and improved failover handling.

Feature toggle

  • Terraform variable: enable_rds_proxy
  • Default: true

When enabled, Lambdas connect through the RDS Proxy. When disabled (enable_rds_proxy = false), Lambdas connect directly to the Aurora cluster endpoint. Both paths use IAM auth tokens for authentication.

Environment variables

VariableDescription
RDS_HOSTConnection host — proxy endpoint or cluster endpoint
RDS_HOSTNAMEReal hostname for IAM token signing (may differ from RDS_HOST when tunneling locally)
RDS_PORTConnection port
RDS_DATABASEDatabase name (postgres)
RDS_DB_USERDatabase username

In AWS, RDS_HOST is set automatically by Terraform via local.database_endpoint, which resolves to the proxy or cluster endpoint based on enable_rds_proxy.

Local development

When connecting through an SSM tunnel, set RDS_HOST=localhost and RDS_HOSTNAME to the cluster endpoint for IAM token signing. See the local development guide for details.

Outbound Connectivity (IPv6 + Optional Proxy)

The REST, Worker, and Org Sync Lambdas run in private subnets and prefer IPv6 egress.

Some third-party endpoints are IPv4-only. To support those calls without a NAT gateway, GitGazer can deploy a small HTTP proxy Lambda outside the VPC:

  1. Caller Lambda invokes the proxy Lambda via the Lambda API.
  2. Proxy Lambda performs the external HTTPS request on behalf of the caller.
  3. Response is returned to the caller Lambda.

Feature toggle

  • Terraform variable: enable_http_proxy
  • Default: true

When enabled, outbound calls that use proxyFetch are relayed through the proxy Lambda by default. When disabled (enable_http_proxy = false), proxyFetch falls back to direct fetchWithRetry.

Disabling the proxy

If your environment does not provide IPv4 internet egress (for example no NAT gateway and no NAT64 path), direct calls to IPv4-only services can time out when enable_http_proxy is disabled.