Deep Space Research Platform
Software Architecture

Prabhu Sadasivam
Sr. Software Architect
ORCID: 0009-0008-0069-693X
Classification: Public

1. Vision & Strategic Intent

1.1 Mission

Build a unified, publicly accessible platform for deep-space scientific research that consolidates real-time telemetry from NASA missions, interstellar object observations, and theoretical cosmology simulations into an integrated analytical and visualization system — while maintaining near-zero operational cost and production-grade reliability.

1.2 Strategic Objectives

ObjectiveOutcome
Scientific accessibilityMake NASA mission data explorable by anyone through a web interface — no specialized tools required
Cross-domain correlationEnable analytical connections across Voyager 1 telemetry, interstellar object tracking, space weather, and black hole cosmology
Reproducible researchPersist every data ingestion with provenance tracking so past analyses can be reproduced even after upstream APIs change
Operational simplicityRun the entire platform on a single EC2 instance with automated recovery — no Kubernetes, no managed services, no vendor lock-in beyond commodity compute
Architectural extensibilityDesign every component — schema, API, templates, ingestion — for additive extension without modifying existing contracts

1.3 Why This Architecture

The deep-space research domain has a distinctive constraint profile:

These constraints drove every major architectural decision: server-side rendering over SPA frameworks, SQLite over managed databases, synthetic fallback over hard failures, and a single-instance deployment over distributed systems.

2. Platform Overview

The Deep Space Research Platform comprises four interconnected projects published under a single domain:

┌──────────────────────────────────────────────────────────────────────────┐
│                     prabhusadasivam.com                                  │
│                                                                          │
│  ┌─────────────────────┐  ┌─────────────────────┐  ┌────────────────┐   │
│  │   Voyager 1 Suite   │  │   3I/ATLAS Research  │  │  Black Hole    │   │
│  │   6 analysis pages  │  │   Jupyter pipeline   │  │  Simulation    │   │
│  │   7 API endpoints   │  │   Ephemerides + MAST │  │  Bouncing      │   │
│  │   11 HTML templates │  │   Orbital elements   │  │  cosmology     │   │
│  └─────────┬───────────┘  └──────────┬───────────┘  └───────┬────────┘  │
│            │                         │                       │           │
│            └─────────────┬───────────┘───────────────────────┘           │
│                          ▼                                               │
│              ┌───────────────────────┐                                   │
│              │    Unified Analytics  │                                   │
│              │    Database           │                                   │
│              │    (deep_space_db)    │                                   │
│              └───────────────────────┘                                   │
└──────────────────────────────────────────────────────────────────────────┘
ProjectRepositoryPurpose
Voyager 1 AnalysisPSadasivam/voyager1-analysisFlask web app + scientific analysis: trajectory, plasma waves, electron density, magnetometer, space intelligence
3I/ATLAS ResearchPSadasivam/3I-ATLAS-researchJupyter pipeline for interstellar comet C/2025 N1 (ATLAS): ephemerides, MAST archive queries, orbital elements
Black Hole SimulationPSadasivam/universe-inside-blackholeBouncing cosmology: Schwarzschild radius of total universe mass using Planck 2018 parameters
Unified Analytics DBPSadasivam/deep-space-dbSQLite database consolidating all research data with S3 backup and audit logging

3. System Context & Integration Landscape

3.1 External System Dependencies

                              ┌─────────────────────┐
                              │    prabhusadasivam   │
                              │        .com          │
                              └──────────┬───────────┘
                                         │
         ┌──────────┬──────────┬─────────┼─────────┬───────────┬──────────┐
         ▼          ▼          ▼         ▼         ▼           ▼          ▼
    ┌─────────┐ ┌────────┐ ┌────────┐ ┌──────┐ ┌───────┐ ┌────────┐ ┌──────┐
    │   JPL   │ │  NASA  │ │  NASA  │ │ NASA │ │ NASA  │ │  NOAA  │ │ MAST │
    │HORIZONS │ │  SPDF  │ │  PDS   │ │ NeoWs│ │ DONKI │ │  SWPC  │ │(STScI│
    │         │ │        │ │  PPI   │ │      │ │       │ │        │ │)     │
    └─────────┘ └────────┘ └────────┘ └──────┘ └───────┘ └────────┘ └──────┘
    Trajectory   Magneto-   Plasma     Near-    Solar     Kp Index   HST/JWST
    Ephemerides  meter CDF  Wave CDF   Earth    Flares    Forecast   Archive
                                       Objects  CMEs/GST
Upstream SystemProtocolAuthFailure ModeFallback Strategy
JPL HORIZONSastroquery (HTTP)NoneTimeout / 5xxSynthetic trajectory model
NASA SPDFHTTPS file downloadNone404 / timeoutSynthetic magnetometer data
NASA PDS PPIHTTPS file downloadNone404 / timeoutSynthetic plasma wave generator
NASA NeoWsREST JSONAPI key (env var)Rate limit / 5xx15-min stale cache
NASA DONKIREST JSONAPI key (env var)Rate limit / 5xx15-min stale cache
NOAA SWPCREST JSONNoneTimeout15-min stale cache
MAST (STScI)astroquery (HTTP)NoneTimeoutCached CSVs
MPCStatic filesNoneN/ALocal JSON/obs files

Key design decision: Every external dependency has an explicit fallback path. The platform never returns an error page due to upstream API failure.

3.2 Downstream Consumers

ConsumerInterfaceUsage
Web browsersHTTPS (HTML + embedded base64 images)Primary end-user interface
Search engines/sitemap.xml, /robots.txt, SEO meta tagsDiscovery and indexing
LLM/AI crawlers/ai-index structured knowledge pageMachine-readable research index
SQLite clientsFile-based .db accessAd-hoc research queries
Jupyter notebookspandas.read_sql() via sqlite3Analytical workflows

4. Architecture Principles

These principles govern all design decisions across the platform:

#PrincipleRationaleApplication
1Graceful degradation over hard failureNASA APIs are unreliable; pages must always renderSynthetic fallback generators for every data source
2Server-side rendering over client-side frameworksEliminates JavaScript build toolchain, reduces attack surface, ensures SEOFlask + Jinja2 templates with base64-embedded plots
3Zero third-party runtime dependencies where possibleMinimizes supply chain risk and dependency managementdeep_space_db uses Python stdlib only; web app pins exact versions
4Additive extension, not modificationNew research projects should not require changes to existing codeNew tables, new ingestion functions, new Flask routes — each additive
5Data provenance on every recordResearch integrity requires knowing where data came fromsource column on every row; ingestion_log table
6Cost proportional to valueResearch infrastructure should not cost more than the research itselfSQLite (free), single EC2 (~$15/mo), S3 (< $0.01/mo)
7Operational simplicity over architectural eleganceOne person operates the entire platformSingle process, single instance, systemd restart, git-pull deploys

5. Technology Stack & Decision Rationale

5.1 Stack Overview

LayerTechnologyVersion
LanguagePython3.11+ (EC2), 3.13 (local)
Web frameworkFlaskLatest stable
WSGI serverGunicorn2 workers
Reverse proxyNginxAmazon Linux default
TLSLet's Encrypt / CertbotAuto-renewing
ComputeAWS EC2 t3.small2 vCPU, 2 GB RAM
Static IPAWS Elastic IPAssociated to EC2
DNSGoDaddyA + CNAME records
DatabaseSQLite 3 (WAL)Bundled with Python
Backup storageAWS S3Versioned, private
Process managementsystemdRestart=always
Scientific computingNumPy, SciPy, Matplotlib, Astropy, AstroqueryPinned in requirements.txt

5.2 Key Technology Decisions

Why Flask over Django/FastAPI: Django's ORM, admin panel, and auth middleware are unnecessary for a read-only research site. FastAPI's async model adds complexity with no benefit when every request is a synchronous NASA API call followed by matplotlib rendering. Flask provides the minimal surface needed: routing, Jinja2 templates, and request handling.

Why server-side matplotlib over D3.js/Plotly: Scientific plots require precise control over axes, annotations, colormaps, and dual-axis layouts that matplotlib provides natively. Embedding plots as base64 PNGs in JSON responses eliminates JavaScript rendering, client-side library loading, and cross-browser compatibility issues. The trade-off (no client-side interactivity) is acceptable for a research presentation platform.

Why SQLite over PostgreSQL/DynamoDB: The workload is single-writer, read-heavy, and local. SQLite requires no server process, no connection pooling, no credential management, and no monthly cost. WAL mode enables concurrent reads during ingestion. The 281 TB theoretical limit far exceeds projected needs. If multi-user access becomes necessary, the schema is standard SQL and can migrate to PostgreSQL without DDL changes.

Why AWS CLI over boto3 for S3: The backup script needs exactly three operations: upload, list, download. The AWS CLI handles these with subprocess calls, avoiding a boto3 dependency, its transitive dependency tree, and the associated supply chain surface. For a script that runs once per day, the subprocess overhead is negligible.

Why Gunicorn with 2 workers: Each worker handles one request at a time. Matplotlib is not thread-safe, so preload_app=True with sync workers is the correct model. Two workers provide basic concurrency (one can render a plot while the other serves a cached page) without exceeding the 2 GB RAM of a t3.small.

6. Infrastructure Architecture

6.1 Deployment Topology

                              Internet
                                 │
                            ┌────┴────┐
                            │ GoDaddy │
                            │   DNS   │  A: prabhusadasivam.com → Elastic IP
                            └────┬────┘  CNAME: www → prabhusadasivam.com
                                 │
                    ┌────────────┴────────────┐
                    │    AWS EC2 t3.small      │
                    │    Amazon Linux 2023     │
                    │    Elastic IP attached   │
                    │                          │
                    │  ┌────────────────────┐  │
                    │  │      Nginx         │  │
                    │  │  :80 → 301 HTTPS   │  │
                    │  │  :443 → TLS term   │  │
                    │  │  proxy_pass :8000   │  │
                    │  │  security headers   │  │
                    │  │  dotfile deny       │  │
                    │  └─────────┬──────────┘  │
                    │            │              │
                    │  ┌─────────┴──────────┐  │
                    │  │    Gunicorn        │  │
                    │  │  127.0.0.1:8000    │  │
                    │  │  2 sync workers    │  │
                    │  │  systemd managed   │  │
                    │  └─────────┬──────────┘  │
                    │            │              │
                    │  ┌─────────┴──────────┐  │
                    │  │  Flask Application │  │
                    │  │  11 page routes    │  │
                    │  │  7 API endpoints   │  │
                    │  │  2 utility routes  │  │
                    │  └────────────────────┘  │
                    │                          │
                    └──────────┬───────────────┘
                               │
                    ┌──────────┴───────────────┐
                    │        AWS S3             │
                    │  db-backups/ (versioned)  │
                    └──────────────────────────┘

6.2 Network Security

PortProtocolSourcePurpose
22SSHOperator IP onlyDeployment and maintenance
80HTTP0.0.0.0/0Redirect to HTTPS
443HTTPS0.0.0.0/0Application traffic
8000HTTP127.0.0.1 onlyGunicorn (not internet-exposed)

6.3 Nginx Hardening

# Security headers on every response
X-Frame-Options:           DENY
X-Content-Type-Options:    nosniff
Referrer-Policy:           strict-origin-when-cross-origin

# Deny access to dotfiles (.git, .env, etc.)
location ~ /\. { deny all; }

# Proxy configuration — loopback only
proxy_pass http://127.0.0.1:8000;

6.4 Process Lifecycle

                    Boot
                      │
                      ▼
              systemd starts
            voyager1.service
                      │
                      ▼
              Gunicorn spawns
              2 Flask workers
                      │
              ┌───────┴───────┐
              │               │
           Worker 1        Worker 2
              │               │
              ▼               ▼
         Serve requests  Serve requests
              │
              │ ← Process crash
              ▼
        systemd detects
        exit code ≠ 0
              │
              ▼
        Restart=always
        RestartSec=3
              │
              ▼
        Gunicorn respawns

7. Application Architecture

7.1 Request Flow

Browser GET /trajectory
         │
         ▼
     Nginx (TLS termination, security headers)
         │
         ▼
     Gunicorn → Flask route handler
         │
         ├── render_template("trajectory.html")
         │       ├── nav_caret=True (dropdown nav config)
         │       ├── page-specific meta tags (SEO)
         │       └── Template extends base layout
         │
         └── Template includes <script> that calls /api/trajectory
                    │
                    ▼
              Flask API handler
                    │
                    ├── Try: JPL HORIZONS query (real data)
                    │         │
                    │         ├── Success → matplotlib plot → base64 PNG
                    │         └── Failure ──┐
                    │                       │
                    ├── Fallback: synthetic trajectory model
                    │         │
                    │         └── matplotlib plot → base64 PNG
                    │
                    └── Return JSON:
                          {
                            "plot": "data:image/png;base64,...",
                            "events": [...],
                            "galactic_coords": {...},
                            "data_source": "jpl_horizons" | "synthetic"
                          }

7.2 Rendering Strategy

All visualization follows a consistent server-side rendering pipeline:

  1. Data acquisition — Call external API or generate synthetic data
  2. Scientific computation — NumPy/SciPy processing (filtering, FFT, ridge detection)
  3. Plot generation — Matplotlib with Agg backend (no display server required)
  4. Encodingio.BytesIO → base64 string
  5. Transport — JSON response with embedded base64 PNG
  6. Display — Jinja2 template sets <img src=""> or JavaScript img.src = data.plot

This approach guarantees:

7.3 Caching Architecture

LayerStrategyTTLScope
Space Intelligence APIsIn-memory Python dict15 minutesPer-worker process
Stale cache fallbackReturn last successful response on API failureUntil next successPer-worker process
BrowserStandard HTTP caching headers via NginxNginx defaultsPer-client

Design decision: No external cache (Redis, Memcached) is used. The in-memory approach is sufficient for single-instance deployment and eliminates an infrastructure dependency. If scaling to multiple instances, a shared cache layer would be introduced.

7.4 Template Architecture

All 11 HTML templates share:

Pages are connected through a sequential journey navigation:

Facts → Trajectory → Plasma Waves → Density → Magnetometer → 3I/ATLAS

Each page includes "Previous" / "Next" links, creating a guided research narrative through the data.

8. Data Architecture

8.1 Data Domains

DomainData NatureVolume CharacteristicPrimary Source
Voyager 1 TelemetryTime-series instrument readingsSparse (daily/hourly resolution from 164 AU)NASA SPDF, PDS, JPL HORIZONS
3I/ATLAS TrackingPositional ephemerides + archival observationsBatch (periodic notebook runs)JPL HORIZONS, MAST, MPC
Black Hole SimulationPhysical constants + derived quantitiesStatic (recomputed on demand)Planck 2018 parameters
Space IntelligenceNEO approaches + solar activityStreaming-like (15-min refresh)NASA NeoWs, DONKI, NOAA SWPC
Research InsightsCross-project findings and hypothesesAppend-only (human-authored)Manual entry

8.2 Unified Database Schema

┌──────────────────────────────────────────────────────────────────┐
│                     deep_space_research.db                        │
│                                                                   │
│  VOYAGER 1 (5 tables)          3I/ATLAS (4 tables)               │
│  ┌────────────────────┐        ┌────────────────────┐            │
│  │ magnetic_field     │        │ ephemerides        │            │
│  │ plasma_wave        │        │ mast_observations  │            │
│  │ electron_density   │        │ orbital_elements   │            │
│  │ trajectory         │        │ datasets           │            │
│  │ events             │        └────────────────────┘            │
│  └────────────────────┘                                          │
│                                                                   │
│  BLACK HOLE (1 table)          SPACE INTEL (2 tables)            │
│  ┌────────────────────┐        ┌────────────────────┐            │
│  │ simulations        │        │ neos               │            │
│  └────────────────────┘        │ solar              │            │
│                                └────────────────────┘            │
│                                                                   │
│  METADATA (3 tables)                                             │
│  ┌────────────────────┐                                          │
│  │ research_insights  │  ← cross-project analytical findings     │
│  │ ingestion_log      │  ← every data load audited               │
│  │ s3_backup_log      │  ← every backup audited                  │
│  └────────────────────┘                                          │
└──────────────────────────────────────────────────────────────────┘

8.3 Schema Design Invariants

InvariantImplementationPurpose
Temporal keytimestamp_utc TEXT NOT NULL (ISO 8601)Range queries via string comparison
Provenancesource TEXT DEFAULT '<origin>'Distinguish real vs. synthetic vs. derived data
Audit timestampingested_at TEXT DEFAULT (datetime('now'))Track when data entered the system, independent of observation time
Indexed accessB-tree index on primary timestamp columnSub-millisecond range scans on time-series data
Parameterized writesAll SQL uses ? placeholdersPrevent injection regardless of data content

8.4 Data Lineage

NASA SPDF → voyager1_magneticfield_nTS_analysis.py → /api/magnetometer → JSON
                                                   ↘
                                                    → init_db.py → voyager1_magnetic_field table
                                                                              ↓
                                                                   s3_backup.py → S3

JPL HORIZONS → astroquery → /api/trajectory → JSON
             → astroquery → 3I_ATLAS_research_notebook.ipynb → ephemerides.csv
                                                              → init_db.py → atlas_3i_ephemerides table

Every data point can be traced from its NASA/JPL origin through the ingestion pipeline to the database row, identified by the source column.

9. API Design & Contract

9.1 API Inventory

EndpointMethodParametersResponse Shape
/api/trajectoryGET{ plot, events[], galactic_coords, data_source }
/api/positionGET{ plot, distance_au, coordinates, data_source }
/api/magnetometerGET?days={ plot, statistics{}, data_source }
/api/plasmaGET?hours=&freq_min=&freq_max={ spectrogram, spectrum, time_series, statistics }
/api/densityGET?hours={ process_plot, nasa_plot, statistics }
/api/space-intelligenceGET{ neos[], flares[], cmes[], storms[], kp_index, forecast[], highlights[] }
/api/statusGET{ status, cdflib, data_sources{} }

9.2 Response Contract

All plot-bearing endpoints follow a consistent contract:

{
  "plot": "data:image/png;base64,...",     // Always present
  "data_source": "jpl_horizons|synthetic", // Always present — transparency
  "statistics": { ... },                    // Domain-specific metrics
  "events": [ ... ]                         // Optional: notable data points
}

The data_source field is critical to architectural integrity: it tells the consumer whether they are viewing real NASA data or a synthetic approximation. This transparency extends the provenance principle from the database layer to the API layer.

9.3 Error Handling Contract

API endpoints never return HTTP 5xx. The degradation hierarchy is:

  1. Real data (preferred) — external API succeeded
  2. Cached data — external API failed, in-memory cache is fresh (< 15 min)
  3. Stale cache — external API failed, cache is stale but usable
  4. Synthetic data — no cache available; generate mathematically plausible data
  5. Empty response with explanation — only if generation itself fails (extremely rare)

10. Cross-Project Integration Strategy

10.1 Integration Architecture

┌──────────────┐    File System     ┌──────────────┐
│  3I/ATLAS    │ ──── CSVs/JSONs ──►│  deep_space  │
│  Research    │                     │      _db     │
└──────┬───────┘                     └──────────────┘
       │                                    ▲
       │ PNGs to Images/                    │ CSVs/JSONs
       ▼                                    │
┌──────────────┐                     ┌──────┴───────┐
│  Voyager 1   │ ──── CSVs ────────►│  Black Hole  │
│  Web App     │                     │  Simulation  │
└──────────────┘                     └──────────────┘
       │
       │ Serves all pages under one domain
       ▼
  prabhusadasivam.com
MechanismPatternExample
File-system sharingSibling directoriesinit_db.py reads ../3I-Atlas-Research/ephemerides.csv
Presentation integrationFlask renders templates for all projects/atlas, /blackhole, /mars pages in Voyager 1 app
Analytical integrationresearch_insights table links findings across domains"Voyager 1 measures the interstellar medium that 3I/ATLAS traveled through"

10.2 Integration Design Rationale

Projects are deliberately not microservices. A monolithic Flask application serves all pages because:

This will be revisited if the platform requires multi-team development or independent scaling (see §17).

11. Resilience & Graceful Degradation

11.1 Failure Mode Analysis

FailureDetectionRecoveryUser Impact
NASA API timeoutrequests.Timeout / astroquery exceptionSynthetic data generatorPage renders with approximated data; data_source: synthetic
NASA API rate limitHTTP 42915-min in-memory cache serves stale dataTransparent — data is at most 15 min old
Flask worker crashsystemd detects exit code ≠ 0Restart=always, RestartSec=3< 3 seconds of unavailability
EC2 instance rebootsystemd WantedBy=multi-user.targetAuto-start on bootMinutes of unavailability
Database corruptionPRAGMA integrity_check failurepython s3_backup.py restoreDatabase queries fail until restored (web app is unaffected)
S3 backup deletionMissing object on aws s3 lsS3 versioning recovers previous versionNo user impact
Let's Encrypt renewal failureCertbot logs / browser TLS errorManual certbot renewHTTPS certificate warning
Disk fullWrite failureWAL checkpoint + cleanupIngestion/backup fails; web app continues serving

11.2 Synthetic Data Architecture

The synthetic data generators are not test mocks — they are mathematically grounded models:

GeneratorModelAccuracy
TrajectoryVoyager 1 velocity (17 km/s) extrapolated from last known position< 1% distance error verified against JPL HORIZONS
MagnetometerGaussian noise around 0.1 nT baseline (interstellar medium conditions)Physically plausible range
Plasma waveMulti-frequency synthetic spectrogram with realistic power-law spectrumStructurally accurate; not observation data
Electron densityDerived from synthetic plasma frequencyFormula-exact; input is synthetic

11.3 Resilience Principle

The platform renders every page, every time. No combination of external failures produces a user-facing error. The quality of data may degrade (real → cached → synthetic), but the experience never breaks.

12. Security Architecture

12.1 Defense in Depth

Layer 1: Network
├── Security group: SSH restricted to operator IP
├── HTTP/HTTPS open (required for public website)
└── Gunicorn bound to 127.0.0.1 only

Layer 2: TLS
├── Let's Encrypt certificate (auto-renewal)
├── HTTP → HTTPS redirect (Nginx)
└── HSTS implied by redirect

Layer 3: Nginx
├── X-Frame-Options: DENY
├── X-Content-Type-Options: nosniff
├── Referrer-Policy: strict-origin-when-cross-origin
├── Dotfile access denied (blocks .git, .env)
└── /api/ disallowed in robots.txt

Layer 4: Application
├── Flask debug=False in production
├── SECRET_KEY via environment variable
├── No user input to SQL queries (read-only web interface)
├── Parameterized SQL in all ingestion scripts
└── NASA API key via environment variable

Layer 5: Data
├── SQLite WAL mode (crash consistency)
├── Source provenance on every row
├── .gitignore excludes .db files and .env
└── No PII in any data table

Layer 6: Cloud
├── S3 bucket: all public access blocked
├── S3 versioning: protects against deletion
├── S3 SSE-S3: encryption at rest
├── IAM: scoped credentials recommended
└── AWS CLI: HTTPS enforced for all S3 operations

12.2 Secrets Inventory

SecretLocationIn Source Control?
AWS Access Key / Secret Key~/.aws/credentialsNo
Flask SECRET_KEYEnvironment variable on EC2No
NASA API KeyNASA_API_KEY env varNo
SSH private key~/voyager1-deploy.pem (local)No
S3 bucket nameS3_BACKUP_BUCKET env varNo

No secrets exist in any committed file across all four repositories.

12.3 STRIDE Threat Model

A complete STRIDE analysis is documented separately, covering 14 identified threats across Spoofing, Tampering, Repudiation, Information Disclosure, DoS, and Elevation of Privilege — with trust boundary diagrams, asset inventory with CIA ratings, attack surface assessment, and incident response playbooks.

13. Scalability & Growth Strategy

13.1 Current Capacity

DimensionCurrentComfortable Ceiling
Concurrent users~5–10 (2 Gunicorn workers)~50 with 4 workers
Database rows8610 million+ (SQLite with indexes)
Database size116 KB1 GB+
S3 backup cost< $0.01/mo< $1/mo at 10 GB
Page load time2–5 sec (API-dependent)Cacheable to < 1 sec

13.2 Scaling Triggers & Responses

TriggerThresholdResponse
Concurrent users > 50Gunicorn worker saturationIncrease workers (up to CPU count); add response caching
Concurrent users > 200EC2 t3.small limitUpgrade instance type; add CloudFront CDN for static assets
Concurrent users > 1000Single-instance limitAdd ALB + multiple EC2 instances; externalize cache to ElastiCache
Database > 1 GBSQLite performance riskEvaluate DuckDB (analytical) or PostgreSQL RDS (multi-user)
Multiple contributorsConcurrent write contentionMigrate to PostgreSQL; add application-level auth
Multiple research projects > 6Template/route sprawlExtract shared framework; consider project-specific Flask Blueprints

13.3 What Will NOT Change

These are architectural invariants that hold regardless of scale:

14. Operational Excellence

14.1 Deployment Model

AspectCurrent StateTarget State
Deployment methodgit pull + systemctl restart via SSHGitHub Actions → EC2 deploy
Rollbackgit revert + systemctl restartAutomated rollback on health check failure
Health checkManual curl / browser/api/status endpoint (exists); automated monitoring pending
Log accessjournalctl -u voyager1 on EC2CloudWatch Logs agent
Uptime monitoringManualExternal ping service (UptimeRobot / AWS Route 53 health check)

14.2 Database Operations

OperationCommandFrequency
Full initpython init_db.pyOn schema change
Re-ingestpython init_db.py --ingest-onlyWhen source data updates
Schema updatepython init_db.py --schema-onlyOn table additions
Backuppython s3_backup.py backupAfter each ingestion (manual; daily cron recommended)
Restorepython s3_backup.py restoreOn corruption or data loss
Audit querySELECT * FROM ingestion_log ORDER BY ingested_at DESCAd-hoc

14.3 Observability

SignalCurrentGap
Application logsstdout → journalctlNo centralized log aggregation
Error trackingLog inspectionNo alerting on exceptions
API latencyNot measuredAdd request timing middleware
UptimeNot monitoredAdd external health check
Data freshnessingested_at column queryableNo automated staleness alerts

15. Risks, Constraints & Trade-Offs

15.1 Architectural Trade-Offs

DecisionWhat We GainWhat We Accept
Server-side renderingSEO, simplicity, no JS build chainNo client-side interactivity on plots
Single EC2 instanceSimplicity, low costSingle point of failure for compute
SQLite over PostgreSQLZero cost, zero ops, portableSingle writer, no concurrent access
Monolithic Flask appOne deploy, shared navigationAll projects coupled in one process
Synthetic fallbackPages always renderUsers may see approximated data
Manual deploymentNo CI/CD infrastructure to maintainHuman error risk; slower deploy cycle
2 Gunicorn workersFits t3.small memoryLimited concurrent request handling

15.2 Technical Debt Register

ItemSeverityEffortImpact if Unaddressed
No CI/CD pipelineMediumMediumManual deploys remain error-prone
No automated testing for Flask routesMediumMediumRegressions detected only in production
No uptime monitoringMediumLowOutages detected by manual observation
No centralized loggingLowMediumDebugging requires SSH to EC2
Root AWS credentials in useHighLowOver-privileged access; security risk
No database encryption at restLowLowAcceptable — no PII or classified data

15.3 Constraints

ConstraintSourceImpact
NASA API rate limitsExternal policyDrives caching strategy (15-min TTL)
Matplotlib not thread-safeLibrary limitationMandates sync Gunicorn workers
SQLite single-writerEngine limitationPrevents concurrent ingestion processes
EC2 t3.small 2 GB RAMInstance typeLimits Gunicorn workers and in-memory data
No PII in scopeData classificationSimplifies security requirements significantly

16. Roadmap & Evolution Path

Phase 1 — Foundation (Complete)

Phase 2 — Operational Maturity

Phase 3 — Data Pipeline Automation

Phase 4 — Analytics & Insights

Phase 5 — Scale (If Warranted)

17. Appendix — Reference

A. Repository Map

RepositoryURLBranch
Voyager 1 Analysisgithub.com/PSadasivam/voyager1-analysismain
3I/ATLAS Researchgithub.com/PSadasivam/3I-ATLAS-researchmain
Black Hole Simulationgithub.com/PSadasivam/universe-inside-blackholemain
Unified Analytics DBgithub.com/PSadasivam/deep-space-dbmain

B. External API Reference

APIEndpointDataAuth
JPL HORIZONSastroquery.jplhorizonsPositions, velocities, ephemeridesNone
NASA SPDFspdf.gsfc.nasa.govMagnetometer CDF/CSV filesNone
NASA PDS PPIpds-ppi.igpp.ucla.eduPlasma wave CDF filesNone
NASA NeoWsapi.nasa.gov/neo/rest/v1/feedNear-Earth objectsAPI key
NASA DONKIapi.nasa.gov/DONKI/{FLR,CME,GST}Solar flares, CMEs, stormsAPI key
NOAA SWPCservices.swpc.noaa.gov/products/Kp index, forecastNone
MAST (STScI)astroquery.mast.ObservationsHST/JWST archive metadataNone
MPCLocal 3I_mpc_orb.jsonOrbital elementsN/A

C. Key Configuration Files

FileLocationPurpose
voyager1.nginx.confvoyager1_project/Nginx reverse proxy + security headers
voyager1.service/etc/systemd/system/ (EC2)systemd service definition
requirements.txtvoyager1_project/Python dependencies
schema.sqldeep_space_db/Database DDL
.gitignoredeep_space_db/Excludes .db, WAL, .env

D. Related Documentation

DocumentLocationScope
Database Architecturedeep_space_db/docs/database-architecture.mdSchema design, ingestion, queries, scalability
Security Threat Modeldeep_space_db/docs/security-threat-model.mdSTRIDE analysis, controls, incident response
AWS Deployment Guidevoyager1_project/docs/aws-deployment.mdEC2 setup, Nginx, Certbot, systemd
Getting Startedvoyager1_project/docs/getting-started.mdLocal development setup