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
- 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.
- Async processing — The Worker Lambda consumes events from SQS, inserts/upserts data into Aurora PostgreSQL, and triggers side effects (WebSocket push, alerting).
- Real-time updates — The Worker pushes workflow updates to connected WebSocket clients via the API Gateway Management API.
- 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.
- 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:
| Workspace | Purpose | Tech Stack |
|---|---|---|
apps/api/ | AWS Lambda backend — REST API, WebSocket handler, worker, alerting | TypeScript, Node.js 24, Drizzle ORM |
apps/web/ | Single-page application frontend | Vue 3, Radix Vue, Tailwind CSS 4, Pinia, Vite |
apps/docs/ | Documentation site (this site) | Docusaurus |
packages/db/ | Shared database schema, types, and client | Drizzle ORM, TypeScript |
packages/import/ | Historical GitHub Actions data backfill utility | TypeScript |
infra/ | Infrastructure as code | Terraform, 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:
| Lambda | Trigger | Purpose |
|---|---|---|
| REST API | API Gateway HTTP | Handles all REST API requests (auth, integrations, workflows, notifications, etc.) |
| WebSocket | API Gateway WebSocket | Manages $connect and $disconnect lifecycle events |
| Worker | SQS event source | Processes webhook events asynchronously — inserts data, pushes WebSocket updates, sends alerts |
| Org Sync | EventBridge schedule | Periodically syncs GitHub organization members to integration memberships |
| HTTP Proxy | Lambda 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
| Variable | Description |
|---|---|
RDS_HOST | Connection host — proxy endpoint or cluster endpoint |
RDS_HOSTNAME | Real hostname for IAM token signing (may differ from RDS_HOST when tunneling locally) |
RDS_PORT | Connection port |
RDS_DATABASE | Database name (postgres) |
RDS_DB_USER | Database 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.
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:
- Caller Lambda invokes the proxy Lambda via the Lambda API.
- Proxy Lambda performs the external HTTPS request on behalf of the caller.
- 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.
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.