Backend Integration & Infrastructure
Categories:
Backend Integration & Infrastructure
This document details the backend infrastructure, database architecture, and integration requirements for the Peregrine mobile application.
Current Status
Development Stage: Mobile app uses MockDataAdapter with no real backend
- Frontend: Complete React Native app (React Native 0.81.5, Expo 54.0.31)
- Backend: Infrastructure code exists but not integrated
- Database: No schema implementation
- Status: MVP/Prototype stage - not production-ready
Infrastructure Overview
Phenom Infrastructure Repository
Location: ~/projects/thephenom-app/phenom-infra
The infrastructure is managed using Terraform (Infrastructure as Code) for AWS deployment.
Stack Components
graph TB
Mobile[Mobile App<br/>React Native] --> ALB[Application Load Balancer]
ALB --> GraphQL[Hasura GraphQL Engine<br/>Port 8080]
ALB --> Auth[Hasura Auth<br/>Port 4000]
ALB --> Storage[Hasura Storage<br/>Port 5000]
ALB --> Functions[Nhost Functions<br/>Port 3000]
GraphQL --> RDS[(PostgreSQL + PostGIS<br/>RDS)]
Auth --> RDS
Storage --> S3[S3 Media Storage]
Functions --> Lambda[Lambda Functions]
Auth --> Cognito[AWS Cognito]
Lambda -.Sync.-> Cognito
style Mobile fill:#e1f5fe
style ALB fill:#fff3e0
style GraphQL fill:#f3e5f5
style Auth fill:#f3e5f5
style Storage fill:#f3e5f5
style Functions fill:#f3e5f5
style RDS fill:#c8e6c9
style S3 fill:#fff9c4
style Cognito fill:#fce4ecTerraform Modules
Networking Module (modules/networking/)
- VPC with public/private subnets
- Multi-availability zone deployment
- NAT gateways for private subnet internet access
- Security groups for service isolation
ALB Module (modules/alb/)
- Application Load Balancer configuration
- Target groups for each service
- Path-based routing rules
- HTTPS/SSL termination
ECS Module (modules/ecs/)
- ECS Fargate cluster
- Task definitions for Hasura services
- Service auto-scaling configuration
- CloudWatch integration
RDS Module (modules/rds/)
- PostgreSQL database setup
- PostGIS extension for geospatial queries
- Automated backups
- Multi-AZ deployment for high availability
Video Upload Module (modules/video-upload/)
- Serverless media upload pipeline
- S3 staging and final buckets
- Lambda validation functions
- API Gateway integration
Media Upload Architecture
graph TB
User[Mobile App User] -->|1. Request Upload URL| API[API Gateway]
API -->|2. Authenticate| Lambda1[Pre-signed URL<br/>Generator Lambda]
Lambda1 -->|3. Validate| Secrets[AWS Secrets Manager]
Lambda1 -->|4. Generate URL| S3Staging[(S3 Staging Bucket<br/>24h Auto-Delete)]
Lambda1 -->|5. Return URL| User
User -->|6. Upload Media| S3Staging
S3Staging -->|7. Trigger| Lambda2[File Validator Lambda]
Lambda2 -->|8a. Check Magic Bytes| Lambda2
Lambda2 -->|8b. Virus Scan Optional| Lambda2
Lambda2 -->|8c. Size Validation| Lambda2
Lambda2 -->|9. Valid File| S3Final[(S3 Final Bucket<br/>Organized by Type)]
Lambda2 -->|10. Invalid| Delete[Delete & Log]
S3Final -->|11. CDN Delivery| CloudFront[CloudFront CDN]
CloudFront --> Mobile[Mobile App Display]
style User fill:#e1f5fe
style API fill:#fff3e0
style Lambda1 fill:#f3e5f5
style Lambda2 fill:#f3e5f5
style Secrets fill:#fce4ec
style S3Staging fill:#ffecb3
style S3Final fill:#c8e6c9
style Delete fill:#ffccbc
style CloudFront fill:#e8eaf6Security Features:
- Password authentication via AWS Secrets Manager
- Time-limited pre-signed URLs (1 hour default)
- Magic byte validation (checks actual file type)
- Optional ClamAV virus scanning
- File size limits (500MB default)
- API rate limiting (10 req/sec)
- Encryption at rest (AES256)
- Private bucket access only
Supported Formats:
- Images: JPEG, PNG, GIF, WebP, SVG, TIFF, BMP
- Videos: MP4, MPEG, QuickTime, AVI, WMV, WebM
Database Architecture
Required Schema (Not Yet Implemented)
PostgreSQL + PostGIS for geospatial queries
erDiagram
users ||--o{ phenom_reports : creates
users ||--o{ user_favorites : has
users {
uuid id PK
string email UK
string password_hash
jsonb profile
timestamp created_at
timestamp updated_at
}
phenom_reports ||--o{ phenom_media : contains
phenom_reports ||--o{ user_favorites : favorited_by
phenom_reports }o--o{ categories : has
phenom_reports {
uuid id PK
uuid user_id FK
geography location
jsonb coordinates
timestamp timestamp
string h3_index
int h3_resolution
text description
}
phenom_media {
uuid id PK
uuid report_id FK
string url
string type
jsonb metadata
string thumbnail_url
}
categories {
uuid id PK
string name UK
text description
string icon
}
user_favorites {
uuid user_id FK
uuid report_id FK
timestamp created_at
}Key Features:
- PostGIS Geography Type for location (earth-aware calculations)
- H3 Index for efficient hex-based spatial queries
- JSONB for flexible coordinate arrays and metadata
- UUID primary keys for distributed system compatibility
Geospatial Indexing Strategy
H3 Hexagonal Indexing:
- Resolution levels 0-15 (0 = continent, 15 = building)
- Mobile app uses resolution 2 for map display (~1,534 km² per hex)
- Database stores both exact coordinates and H3 index for queries
Query Patterns:
-- Find phenoms in specific hex cell
SELECT * FROM phenom_reports WHERE h3_index = '872a1072fffffff';
-- Find phenoms within radius
SELECT * FROM phenom_reports
WHERE ST_DWithin(
location::geography,
ST_MakePoint(-73.9857, 40.7484)::geography,
10000 -- 10km radius
);
-- Find phenoms in neighboring hexes
SELECT * FROM phenom_reports
WHERE h3_index = ANY(h3_k_ring('872a1072fffffff', 1));
API Integration Points
Current Mobile App Architecture
graph LR
subgraph Mobile App
Screens[Screens<br/>Home/Map/Record] --> API[PhenomAPI.current]
API --> Adapter{API Adapter}
Adapter --> Mock[MockDataAdapter<br/>CURRENT]
Adapter -.Future.-> Real[Real Backend Adapter<br/>NEEDED]
end
Real -.-> GraphQL[Hasura GraphQL API]
Real -.-> REST[REST Endpoints]
Real -.-> WS[WebSocket Subscriptions]
style Mock fill:#ffccbc
style Real fill:#c8e6c9
style GraphQL fill:#e8eaf6
style REST fill:#e8eaf6
style WS fill:#e8eaf6Current State: MockDataAdapter.ts
- Generates random mock data
- No network requests
- Hardcoded test data
Required: Real adapter implementing IAPIAdapter interface:
interface IAPIAdapter {
// Phenom queries
getPhenoms(size?: number, since?: Date): Promise<PhenomItem[]>
getPhenom(id: string): Promise<PhenomItem>
getPhenomByH3Cell(h3Index: string): Promise<PhenomItem[]>
// User operations
getUserProfile(userId: string): Promise<PhenomProfile>
updateUserProfile(profile: PhenomProfile): Promise<void>
// Media upload
uploadRecording(recording: RecordingData): Promise<string>
// Search
search(query: string): Promise<PhenomItem[]>
}
Hasura GraphQL Integration
GraphQL Endpoint: https://graphql.phenom.app/v1/graphql
Example Queries:
# Get recent phenoms
query GetRecentPhenoms($limit: Int!) {
phenom_reports(
order_by: { timestamp: desc }
limit: $limit
) {
id
description
timestamp
location
h3_index
user {
id
profile
}
media {
url
type
thumbnail_url
}
categories {
name
icon
}
}
}
# Get phenoms by H3 cell
query GetPhenomsByHex($h3Index: String!) {
phenom_reports(
where: { h3_index: { _eq: $h3Index } }
) {
id
location
timestamp
media {
thumbnail_url
}
}
}
# Create new phenom report
mutation CreatePhenomReport($report: phenom_reports_insert_input!) {
insert_phenom_reports_one(object: $report) {
id
timestamp
}
}
# Subscribe to new phenoms (real-time)
subscription NewPhenoms {
phenom_reports(
order_by: { timestamp: desc }
limit: 10
) {
id
timestamp
location
}
}
Authentication:
- JWT token from Hasura Auth service
- Stored in MMKV encrypted storage
- Sent as
Authorization: Bearer <token>header
Authentication Flow
sequenceDiagram
participant App as Mobile App
participant Auth as Hasura Auth
participant Cognito as AWS Cognito
participant GraphQL as Hasura GraphQL
App->>Auth: POST /signup<br/>{email, password}
Auth->>Cognito: Create user
Cognito-->>Auth: User created
Auth->>GraphQL: Create user profile
Auth-->>App: {accessToken, refreshToken}
Note over App: Store tokens in<br/>MMKV (encrypted)
App->>GraphQL: Query with JWT
GraphQL->>GraphQL: Validate token
GraphQL-->>App: Protected data
Note over App: Token expires
App->>Auth: POST /token/refresh<br/>{refreshToken}
Auth-->>App: {newAccessToken}Token Management:
- Access token: 15 minutes expiry
- Refresh token: 30 days expiry
- Automatic refresh before expiration
- Secure storage in MMKV (encrypted)
Mobile App Integration:
// app/context/AuthContext.tsx (enhanced needed)
const login = async (email: string, password: string) => {
const response = await fetch('https://auth.phenom.app/signin/email-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
})
const { session } = await response.json()
// Store tokens
await storage.save('authToken', session.accessToken)
await storage.save('refreshToken', session.refreshToken)
setAuthToken(session.accessToken)
setAuthEmail(email)
}
Required Backend Work
Phase 1: Core Infrastructure (DevOps)
Tasks:
- ✅ Terraform infrastructure code (COMPLETE)
- ⏳ Deploy development environment
- ⏳ Configure DNS and SSL certificates
- ⏳ Set up monitoring (CloudWatch)
- ⏳ Configure backups and disaster recovery
Owner: DevOps Engineer Timeline: 2-3 weeks Dependencies: AWS account, domain registration
Phase 2: Database Setup (DBA)
Tasks:
- ⏳ Design complete database schema
- ⏳ Create migration scripts
- ⏳ Set up PostGIS extension
- ⏳ Implement H3 functions
- ⏳ Create indexes for performance
- ⏳ Set up replication and backups
Owner: Database Administrator Timeline: 2 weeks Dependencies: Phase 1 complete
Database Optimization:
-- Spatial index for location queries
CREATE INDEX idx_phenom_reports_location
ON phenom_reports USING GIST(location);
-- H3 index for hex queries
CREATE INDEX idx_phenom_reports_h3
ON phenom_reports(h3_index);
-- Timestamp index for recent queries
CREATE INDEX idx_phenom_reports_timestamp
ON phenom_reports(timestamp DESC);
-- User reports index
CREATE INDEX idx_phenom_reports_user
ON phenom_reports(user_id);
Phase 3: API Integration (Backend Developer)
Tasks:
- ⏳ Implement GraphQL adapter in mobile app
- ⏳ Add authentication flow
- ⏳ Implement media upload
- ⏳ Add real-time subscriptions
- ⏳ Error handling and retry logic
- ⏳ Offline queue for uploads
Owner: API Developer Timeline: 3-4 weeks Dependencies: Phase 1 & 2 complete
Phase 4: Sensor & Media Integration (Mobile Developer)
Tasks:
- ⏳ Integrate Expo Location API
- ⏳ Implement camera/video capture
- ⏳ Add sensor data collection (accelerometer, compass)
- ⏳ Implement media compression
- ⏳ Background upload queue
Owner: Frontend Developer Timeline: 2-3 weeks Dependencies: Phase 3 complete
Environment Configuration
Development Environment
# Mobile App (.env.development)
API_URL=https://dev-api.phenom.app
GRAPHQL_URL=https://dev-graphql.phenom.app/v1/graphql
AUTH_URL=https://dev-auth.phenom.app
STORAGE_URL=https://dev-storage.phenom.app
MAPBOX_TOKEN=pk.eyJ1IjoicGhlbm9tam9uIi...
# Backend (Terraform variables)
environment = "development"
aws_region = "us-east-1"
vpc_cidr = "10.0.0.0/16"
enable_nat_gateway = true
database_instance_class = "db.t3.medium"
Production Environment
# Mobile App (.env.production)
API_URL=https://api.phenom.app
GRAPHQL_URL=https://graphql.phenom.app/v1/graphql
AUTH_URL=https://auth.phenom.app
STORAGE_URL=https://storage.phenom.app
MAPBOX_TOKEN=pk.eyJ1IjoicGhlbm9tam9uIi...
# Backend (Terraform variables)
environment = "production"
aws_region = "us-east-1"
vpc_cidr = "10.0.0.0/16"
enable_nat_gateway = true
enable_multi_az = true
database_instance_class = "db.r5.large"
backup_retention_days = 30
Deployment Process
Infrastructure Deployment
# Navigate to environment
cd ~/projects/thephenom-app/phenom-infra/environments/development
# Initialize Terraform
terraform init
# Review plan
terraform plan
# Apply infrastructure
terraform apply
# Get outputs
terraform output
Outputs:
alb_dns_name = "phenom-dev-alb-123456789.us-east-1.elb.amazonaws.com"
graphql_endpoint = "http://phenom-dev-alb-123456789.us-east-1.elb.amazonaws.com:8080"
auth_endpoint = "http://phenom-dev-alb-123456789.us-east-1.elb.amazonaws.com:4000"
Mobile App Configuration
After backend deployment, update mobile app config:
// app/config/config.prod.ts
export const config = {
apiUrl: process.env.API_URL || "https://api.phenom.app",
graphqlUrl: process.env.GRAPHQL_URL || "https://graphql.phenom.app/v1/graphql",
authUrl: process.env.AUTH_URL || "https://auth.phenom.app",
storageUrl: process.env.STORAGE_URL || "https://storage.phenom.app",
}
Monitoring & Observability
CloudWatch Metrics:
- ECS service health
- API response times
- Database connections
- Error rates
Logging:
- Application logs → CloudWatch Logs
- Access logs → S3
- Audit logs → CloudWatch Insights
Alerts:
- High error rate (>5%)
- Database CPU >80%
- Service downtime
- Failed deployments
Security Considerations
Infrastructure:
- Private subnets for services
- Security groups with least privilege
- AWS Secrets Manager for credentials
- Encryption at rest and in transit
- Regular security patches
Application:
- JWT authentication
- Rate limiting
- Input validation
- SQL injection prevention (Hasura parameterized queries)
- XSS protection
Cost Estimates
Development Environment (Monthly):
- ECS Fargate: $50-100
- RDS PostgreSQL: $50-150
- ALB: $20-30
- S3 Storage: $10-30
- Data Transfer: $20-50
- Total: ~$150-360/month
Production Environment (Monthly):
- ECS Fargate (with auto-scaling): $200-500
- RDS PostgreSQL (Multi-AZ, larger instance): $300-600
- ALB: $30-50
- S3 Storage + CloudFront: $100-300
- Data Transfer: $100-300
- Total: ~$730-1,750/month
Next Steps
- Review infrastructure code in
phenom-infrarepository - Deploy development environment
- Implement database schema
- Build GraphQL adapter for mobile app
- Integrate authentication flow
- Test end-to-end data flow
- Deploy staging environment
- Conduct load testing
- Plan production deployment
Internal Resources
Related Documentation
- Architecture Overview - Mobile app architecture
- Features Overview - Custom Phenom features
- Sensors - Device sensor integration
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.