Skip to content

Infrastructure Layers

Runtime behavior within each layer — how components interact during normal operation. For Terraform modules and design decisions, see System Overview. For schemas and key layouts, see Data Contract.

Copies recent RINEX
Receiver Independent Exchange Format — standard GNSS observation file format synced from GeoNet and calibrated by the processor.
from GeoNet
GeoNet open data — public S3 bucket `geonet-open-data` with GNSS RINEX hourly files under `gnss/rinexhourly/`. Not owned by this stack; no push notification when new files arrive.
into the private data lake
Private S3 bucket holding raw RINEX under `raw/rinexhourly/` and processed TEC output under `processed/tec/`.
under raw/rinexhourly/. A new object in the data lake is what triggers processing ( S3
Amazon Simple Storage Service — data lake bucket for raw ingest and processed TEC output; S3 events trigger processing.
ObjectCreated → SQS
Amazon Simple Queue Service — buffers ingest and reprocess messages between S3/API and the processor Lambda.
).

ComponentRuntime role
EventBridge Scheduler
AWS EventBridge Scheduler — triggers ingest-sync Lambda on a recurring UTC schedule (default: hourly).
Poll cadence (default rate(1 hour)); invokes ingest-sync
Ingest_Sync_Lambda
Ingest-sync Lambda (`services/ingest-sync/`) — polls GeoNet on schedule and copies recent RINEX into the data lake (workaround for no source-bucket event subscription).
List GeoNet prefix, copy new files into raw/rinexhourly/{year}/{doy}/

Per invocation: compute rolling UTC window from LOOKBACK_HOURS (default 1) → list s3://geonet-open-data/gnss/rinexhourly/ → skip objects already in the data lake → copy the rest. Ingest-sync does not enqueue SQS
Amazon Simple Queue Service — buffers ingest and reprocess messages between S3/API and the processor Lambda.
directly.

Verify: EventBridge Scheduler · Manual Ingest · S3 key patterns (raw layout)

Calibrates raw RINEX into TEC
Total Electron Content — integrated electron density along the GNSS signal path; primary calibrated output of the processor.
with PyTECGg
PyTECGg — Python library performing TEC calibration on GNSS RINEX observations inside the processor container.
inside an SQS-triggered Lambda container
Processor Lambda container — runs PyTECGg calibration per SQS message; adopted when a Batch on Fargate parallel-execution quota increase was rejected. Image from `ghcr.io/platformfuzz/tec-processor-image` mirrored to ECR.
(see design notes for why not Batch on Fargate).

QueueFed byConcurrency (default)Path
Process_Queue
SQS standard queue — receives S3 ObjectCreated notifications for new raw RINEX files; triggers processor Lambda ingest path.
S3 ObjectCreated on raw/ keys15Scheduled ingest
Reprocess_Queue
SQS standard queue — buffers reprocessing job messages from the Reprocess API with lower concurrency than ingest.
Reprocess API
Reprocess API Lambda (`services/reprocess-api/`) — accepts `/reprocess` jobs, writes DynamoDB records, enqueues Reprocess_Queue.
2Operator jobs

Both queues: visibility timeout 900s, batch_size=1, ReportBatchItemFailures, DLQ
Dead-letter queue — SQS queue receiving messages that exceeded maxReceiveCount (5). CloudWatch alarms fire when visible count ≥ 1.
after 5 failed receives.

Processor invocation: read one SQS message → load raw RINEX from raw/rinexhourly/ → run PyTECGg (nav files from BKG) → write Parquet
Columnar file format — primary processed output for efficient Query API range scans; JSON is a fallback when `pyarrow` is unavailable.
/JSON to processed/tec/station={station}/year={year}/doy={doy}/ → update Jobs table
DynamoDB table keyed by `job_id` — stores reprocess job metadata, parameters, status, and output references.
when job_id is present. Timeout 900s; memory 2048 MiB. Throughput is capped by per-queue concurrency and account Lambda concurrency.

Verify: SQS Queues · Processor Lambda · S3 Processed Output · Parquet output

Exposes processed TEC through API Gateway
Amazon API Gateway — REST API exposing `/catalog`, `/query`, and `/reprocess`. Browser CORS is locked to the Amplify hostname; CLI clients call the API Gateway URL directly.
and an Amplify
AWS Amplify — hosts the Vite portal SPA. This walkthrough deploys via manual zip upload (no Git connection required).
portal. Clients never read the data lake or DynamoDB
Amazon DynamoDB — Jobs table tracks reprocessing job status by `job_id` (queued → processing → completed/failed).
directly.

EndpointLambdaRuntime role
GET /catalogQuery APIPrefix-list stations and (year, doy) under processed/tec/
GET /queryQuery APIRange-read Parquet/JSON from S3; sanitize non-finite floats
POST /reprocessReprocess APIValidate params, create job record, enqueue Reprocess_Queue
GET /reprocess/{job_id}Reprocess APIPoll job status from DynamoDB

Browser CORS locks to the Amplify hostname after CORS Lockdown. The portal (Vite SPA in web/) polls /catalog and /query for charts and IPP
Ionospheric Pierce Point — geographic location where the satellite signal intersects the ionospheric shell; plotted on the portal IPP map.
maps; the reprocess panel calls /reprocess.

Request/response shapes, query limits (QUERY_MAX_ROWS=2000, 7-day window), and reprocess allowlists are in API Response Schemas and DynamoDB Jobs Table.

Verify: REST API · Reprocess Workflow · Portal

Owned by the observability Terraform module. Monitors:

  • DLQs — visible messages on ingest and reprocess dead-letter queues
  • Processor — Lambda errors and throttles
  • Queues — depth and oldest-message age on Process_Queue and Reprocess_Queue
  • Ingest — ingest-sync Lambda errors

Alarms publish to an SNS
Amazon Simple Notification Service — publishes CloudWatch alarm notifications; subscribe an email endpoint after deploy.
topic. The event-driven-platform dashboard aggregates alarm status, queue metrics, and Lambda throughput.

Alarm names, SNS subscription, and dashboard verification: Alarms and Dashboard.