# Data models
Source: https://docs.feedaura.in/engineering/architecture/data-models
Core entities, their key fields, relationships, and where they live.
This page documents the primary domain entities. For schema definitions, see the migration files in the Core API repo.
## Core entities
### User
Represents an authenticated person. One user can belong to multiple organizations.
| Field | Type | Description |
| --------------- | --------- | ---------------------- |
| `id` | UUID | Primary key |
| `email` | string | Unique, used for login |
| `created_at` | timestamp | Account creation time |
| `last_login_at` | timestamp | Last successful auth |
### Organization
A company or team account. The primary billing and access control boundary.
| Field | Type | Description |
| ---------- | --------- | --------------------------- |
| `id` | UUID | Primary key |
| `name` | string | Display name |
| `plan` | enum | `free`, `pro`, `enterprise` |
| `owner_id` | FK → User | Billing owner |
### Membership
Junction table linking users to organizations with a role.
| Field | Type | Description |
| ----------- | ----------------- | -------------------------- |
| `user_id` | FK → User | |
| `org_id` | FK → Organization | |
| `role` | enum | `owner`, `admin`, `member` |
| `joined_at` | timestamp | |
## Relationships
```mermaid theme={null}
graph LR
User --- Membership
Organization --- Membership
User --- Organization
```
A user can be a member of many organizations. An organization can have many members. The `Membership` table holds the role for each pair.
## Data storage
| Data type | Storage | Notes |
| --------------- | -------------------------- | ------------------------------- |
| Relational data | Postgres | Primary store, via Core API |
| Sessions | Redis | TTL-based, auto-expire |
| File uploads | S3-compatible object store | Referenced by URL in Postgres |
| Search index | \[Search service] | Synced from Postgres via worker |
## Sensitive fields
The following fields are encrypted at rest and must never appear in logs:
* `User.password_hash`
* Payment method tokens (stored in your payment processor, referenced by ID only)
* Any field containing PII in audit logs
If you're adding a new field that contains PII or credentials, flag it in your PR for security review.
# Architecture
Source: https://docs.feedaura.in/engineering/architecture/index
Overview of our services and how they fit together.
This section documents the high-level architecture of our systems. For detailed runbooks on specific services, check the service's own README or ask in `#eng`.
The main services, what they do, and how they communicate.
Core entities, their relationships, and where they live.
# Services overview
Source: https://docs.feedaura.in/engineering/architecture/services-overview
The main services that make up our platform, what each one does, and how they communicate.
This page gives a high-level map of our backend services. Each service has its own README with deeper documentation.
## Service map
```mermaid theme={null}
graph TD
Client([Client]) --> GW[API Gateway]
GW --> Auth[Auth Service]
GW --> Core[Core API]
GW --> Worker[Worker Service]
Core --> DB[(Database\nprimary store)]
Core --> Cache[(Cache\nin-memory)]
Worker --> DB
Worker --> Cache
Core -->|publishes jobs| Queue[[Job Queue]]
Worker -->|consumes jobs| Queue
```
## Services
### API Gateway
The public-facing entry point. Handles routing, rate limiting, and authentication checks before forwarding requests to downstream services. Deployed on \[Platform].
**Repo:** `api-gateway`
### Auth Service
Manages user identity, sessions, and permissions. Integrates with your identity provider for SSO. All authentication decisions are delegated here — other services call Auth to validate tokens.
**Repo:** `auth-service`
### Core API
The main application backend. Handles business logic for the primary product domain. Owns the primary database.
**Repo:** `core-api`
### Worker Service
Processes background jobs: email delivery, async data processing, scheduled tasks, and webhook delivery. Consumes from the job queue.
**Repo:** `worker`
## Communication patterns
* **Synchronous:** Services communicate via internal HTTP APIs. Auth headers are passed through and validated at each service boundary.
* **Asynchronous:** Workers consume from the job queue. The Core API publishes jobs; workers process them independently.
* **Events:** Significant domain events (user created, subscription changed) are published to the event bus for downstream consumers.
## Environments
| Environment | Purpose | Access |
| ----------- | --------------------------- | ---------------- |
| Local | Development | All engineers |
| Staging | Pre-production verification | All engineers |
| Production | Live traffic | Deploy tool only |
# Deployment
Source: https://docs.feedaura.in/engineering/deployment
How code goes from a merged PR to production, and how to roll back when something goes wrong.
We use a trunk-based deployment model. Merging to `main` triggers a staging deploy automatically; production deploys are triggered manually after verification.
## Flow overview
```
feature branch → PR review → merge to main → auto-deploy to staging → manual promote to production
```
## Deploying to staging
Every merge to `main` triggers a staging deployment automatically via CI. You don't need to do anything. Check the `#deploys` Slack channel for status notifications.
Staging deployments take approximately 5–10 minutes. If a deploy fails, CI will post the error in `#deploys` with a link to the failed run.
## Promoting to production
Once a change is verified in staging:
1. Go to the deploy tool (link in `#deploys` channel description).
2. Select the staging build you want to promote.
3. Click **Promote to production**.
4. Monitor the `#deploys` channel for confirmation or errors.
Production deploys require at least one engineer who didn't author the change to click promote. This is a soft guard — use judgment in an emergency.
## Feature flags
Most new features are deployed behind a feature flag to decouple deploy from release. Flags are managed in \[Flag Tool Name]. Ask your tech lead about the flag naming convention and cleanup process.
## Rollbacks
If a production deploy causes an incident:
1. Use the deploy tool to roll back to the previous production build immediately.
2. Don't wait to diagnose — roll back first, investigate after.
3. File an [incident](/engineering/incident-response) and start a postmortem if users were affected.
Rolling back takes about 2 minutes. It's safe and reversible — do it early.
## Database migrations
Migrations run automatically as part of the deploy pipeline. Backward-incompatible migrations require a multi-phase deploy — ask in `#eng` before merging if your migration drops a column or changes a type.
## Deploy freeze windows
We freeze production deploys during major events or the last business day before a holiday. The `#deploys` channel will pin a message when a freeze is active.
# Developer setup
Source: https://docs.feedaura.in/engineering/dev-setup
Get your local environment running from a fresh machine in under an hour.
This guide assumes a fresh macOS machine with your company laptop already enrolled in MDM. For Windows, see the Windows setup note at the bottom.
## Prerequisites
Before you start, make sure you have:
* Company laptop with MDM enrolled — see [laptop setup](/onboarding/tools/laptop-setup)
* VPN connected — see [VPN setup](/onboarding/tools/vpn-setup)
* Git repository access — see [account access](/onboarding/tools/account-access)
## Step 1: Install core tooling
Run the bootstrap script — your tech lead will share the link on your first day:
```bash theme={null}
/bin/bash -c "$(curl -fsSL https://setup.yourcompany.com/bootstrap.sh)"
```
If you'd rather install manually, the script installs: a package manager, git, your language runtimes, Docker, and your IDE.
## Step 2: Clone the main repository
```bash theme={null}
mkdir ~/code && cd ~/code
git clone git@git.yourcompany.com:your-repo.git
```
If `git clone` fails with a permission error, your SSH key isn't authorized. Ask your tech lead to check your access.
## Step 3: Set up environment variables
Each repo has a `.env.example` in the root. Copy it:
```bash theme={null}
cp .env.example .env.local
```
Fill in the required values — ask your tech lead or check the `#eng-setup` Slack channel for development secrets. Do not commit `.env.local`.
## Step 4: Install dependencies and run locally
```bash theme={null}
cd your-repo
npm install
npm run dev
```
The app should be running at `http://localhost:3000`. If you hit errors, check the repo's own `README.md` for service-specific requirements (databases, queues, etc.).
## Step 5: Verify your setup
Run the test suite to confirm everything is wired up:
```bash theme={null}
npm test
```
All tests should pass on a fresh clone. If they don't, post in `#eng-setup` with the error output before debugging solo.
## Windows
We don't officially support Windows for local development. WSL2 works for most engineers, but you'll need to adapt some steps. Check with your tech lead before your start date if you prefer Windows.
## Getting help
Post in `#eng-setup` on Slack. Include your OS version, the command you ran, and the full error output.
# Incident response
Source: https://docs.feedaura.in/engineering/incident-response/index
How we detect, respond to, and learn from production incidents.
When something breaks in production, the goal is to restore service as quickly as possible — then understand why.
## Severity levels
| Level | Description | Response target |
| ----- | --------------------------------------------- | -------------------- |
| SEV-1 | Production down or data loss | Immediate, all hands |
| SEV-2 | Significant degradation, major feature broken | Within 30 minutes |
| SEV-3 | Minor degradation, workaround available | Within 2 hours |
| SEV-4 | Cosmetic or low-impact issue | Next business day |
## Responding to an alert
1. **Acknowledge** the alert in your alerting tool to signal you're on it.
2. **Assess severity** — is this SEV-1/2 or lower?
3. **Open a war room** — for SEV-1/2, create a Slack thread in `#incidents` and invite your on-call partner.
4. **Mitigate first** — roll back, disable a feature flag, or scale up before diagnosing root cause.
5. **Communicate** — post updates to `#incidents` every 15 minutes until resolved.
6. **Resolve and document** — mark the incident resolved and file a postmortem for SEV-1/2.
Rotation schedule, escalation paths, and what to do when you're paged.
How to write a blameless postmortem and drive follow-through.
# On-call expectations
Source: https://docs.feedaura.in/engineering/incident-response/on-call
How the on-call rotation works, what's expected of you, and how to escalate.
On-call responsibility rotates weekly among engineers on each team. Being on-call means you're the first responder for production alerts during your shift.
## Rotation schedule
Check your team's on-call schedule in NightWatch. Schedules are set four weeks in advance. If you need to swap a shift, arrange it directly with a teammate and update the schedule — don't just not show up.
New engineers join the rotation after 60 days. Your first few on-call weeks are shadowed — you respond, but a senior engineer is on secondary in case you need backup.
## Before your shift
* Confirm your phone number is correct in the alerting tool.
* Check `#deploys` for any recent changes that might be fragile.
* Review any open SEV-3 issues that could escalate.
## During your shift
**Availability:** Respond to pages within 5 minutes during business hours, within 15 minutes outside business hours. If you can't respond within that window, escalate to secondary immediately.
**For each alert:**
1. Acknowledge the alert to stop re-paging.
2. Triage: is this a real issue or noise? If noise, resolve and file a ticket to fix the alert.
3. If real, follow the [incident response process](/engineering/incident-response).
**Keeping notes:** Keep a running Slack thread in `#incidents` even for small issues. It creates a record and helps the next on-call engineer understand what happened.
## Escalation path
If you've been investigating for 15 minutes and are stuck:
1. Page the secondary on-call engineer.
2. If still stuck after another 15 minutes, escalate to your engineering manager.
Don't wait until you're really stuck. Asking for help quickly is the right call.
## After your shift
Hand off any open issues to the next on-call engineer in `#incidents`. Include: what happened, current status, and what to watch for.
## On-call compensation
On-call shifts outside of business hours are compensated. See HR or your manager for current rates.
# Postmortem process
Source: https://docs.feedaura.in/engineering/incident-response/postmortem
How to write a blameless postmortem, facilitate the review, and make sure action items land.
Postmortems are required for all SEV-1 and SEV-2 incidents, and optional for recurring SEV-3 patterns. The goal is learning, not blame.
## Blameless means
Blameless means we focus on what failed in the system — processes, tooling, alerting, communication — not on who made a mistake. Engineers make good decisions with the information available at the time. The postmortem identifies where the system let them down.
## Timeline
| Timing | Action |
| ----------------------------- | ------------------------------------------------------- |
| Within 24 hours of resolution | Create the postmortem doc from the template |
| Within 48 hours | Draft the timeline and contributing factors |
| Within 5 business days | Hold the postmortem review meeting |
| Within 2 weeks | Action items assigned and tracked in your issue tracker |
## Postmortem template
Create a new doc in your wiki using the Postmortem template. Fill in:
1. **Incident summary** — one paragraph: what happened, when, and what the impact was.
2. **Timeline** — chronological log of events (use UTC). Include when the issue started, when it was detected, key actions taken, and when it was resolved.
3. **Root cause** — what was the underlying cause? Use "5 Whys" if helpful.
4. **Contributing factors** — what else made this worse or harder to detect?
5. **Impact** — number of users affected, duration, data involved.
6. **What went well** — things that helped during response.
7. **Action items** — concrete, assigned, with due dates. At least one per significant contributing factor.
## The review meeting
Keep it to 30–45 minutes. The incident owner facilitates. Everyone who was involved should attend; others are welcome.
Agenda:
1. Walk through the timeline (10 min)
2. Discuss root cause and contributing factors (10 min)
3. Review and assign action items (15 min)
Don't re-hash decisions made during the incident. Focus on what to do differently next time.
## Action items
Action items without owners don't get done. Every item needs:
* A clear description of what "done" looks like
* A single owner (not a team)
* A due date
Track them in your issue tracker. The engineering manager reviews open postmortem action items in the weekly team meeting.
# Engineering
Source: https://docs.feedaura.in/engineering/index
Development setup, deployment processes, incident response, and architecture documentation.
This section covers the technical foundations of how we build and operate our systems.
## Get started
Get your local environment running from a fresh machine.
## Reference
How code goes from a merged PR to production.
On-call expectations, escalation paths, and postmortem process.
Services overview and data models.
# React Application Deployment on AWS EC2 with Nginx
Source: https://docs.feedaura.in/frameworks/react/react-ec2-deployment
Step-by-step guide to deploying a React application on an AWS EC2 instance behind Nginx, with a custom subdomain, HTTPS, and production hardening.
## Architecture
```text theme={null}
User Browser
↓
react.vnta.agency
↓
DNS Record (A Record)
↓
AWS EC2 Public IP
↓
Nginx Web Server
↓
React Build Files
```
## 1. Launch EC2 instance
**Purpose:** EC2 is the Linux server that hosts the React application.
**Configuration:**
* OS: Ubuntu 24.04 LTS
* Instance type: `t3.micro` (learning / small projects)
* Key pair: `.pem` file
* Public IP enabled
## 2. Configure security group
Security Groups act as a firewall for the EC2 instance.
**Inbound rules:**
| Type | Port | Purpose |
| ----- | ---- | ---------------------- |
| SSH | 22 | Remote server access |
| HTTP | 80 | Website traffic |
| HTTPS | 443 | Secure website traffic |
**Why:**
* Without port `22` — cannot SSH into the server
* Without port `80` — website won't load over HTTP
* Without port `443` — HTTPS won't work
Don't open unnecessary ports (`3000`, `5000`, `8000`, `8080`). Only expose what you actually need.
## 3. Connect to EC2
```bash theme={null}
ssh -i mykey.pem ubuntu@EC2_PUBLIC_IP
```
* `ssh` — Secure Shell. Encrypted connection to the server.
* `-i mykey.pem` — use the AWS private key for authentication.
* `ubuntu` — default Ubuntu user.
* `EC2_PUBLIC_IP` — server address.
## 4. Update the server
```bash theme={null}
sudo apt update
sudo apt upgrade -y
```
Updates package repository info and installs the latest security patches.
## 5. Install Nginx
```bash theme={null}
sudo apt install nginx -y
```
Nginx serves the React build files.
```text theme={null}
Linux Server → Nginx → Website Available
```
## 6. Verify Nginx
```bash theme={null}
systemctl status nginx
```
Expected: `active (running)`
Open `http://EC2_PUBLIC_IP` — you should see **Welcome to nginx**.
## 7. Enable Nginx on boot
```bash theme={null}
sudo systemctl enable nginx
```
Ensures Nginx starts automatically if the server restarts.
## 8. Build the React application
On your local machine:
```bash theme={null}
npm install
npm run build
```
Output:
```text theme={null}
build/
├── index.html
├── static
└── assets
```
Browsers can't run `.jsx`, `.tsx`, or Tailwind source directly. The build converts everything into plain HTML, CSS, and JavaScript.
## 9. Create the website directory
On EC2:
```bash theme={null}
sudo mkdir -p /var/www/react-app
```
By Linux convention, `/var/www` is used for web applications.
## 10. Transfer the React build
From your local machine:
```bash theme={null}
scp -i mykey.pem -r build/* ubuntu@EC2_PUBLIC_IP:/home/ubuntu/
```
* `scp` — Secure Copy. Transfers files over SSH.
* `-r` — recursive copy.
## 11. Move build files into place
SSH back into the server:
```bash theme={null}
ssh -i mykey.pem ubuntu@EC2_PUBLIC_IP
```
Move files:
```bash theme={null}
sudo cp -r /home/ubuntu/* /var/www/react-app/
```
Verify:
```bash theme={null}
ls /var/www/react-app
# index.html static
```
## 12. Configure Nginx
```bash theme={null}
sudo nano /etc/nginx/sites-available/default
```
Replace contents with:
```nginx theme={null}
server {
listen 80;
root /var/www/react-app;
index index.html;
location / {
try_files $uri /index.html;
}
}
```
## 13. Understanding the Nginx config
**`listen 80;`** — Nginx listens for HTTP traffic on port 80.
**`root /var/www/react-app;`** — Location of website files.
**`index index.html;`** — Homepage file.
**`try_files $uri /index.html;`** — Critical for React Router.
Without it, paths like `/about`, `/dashboard`, `/contact` return `404 Not Found`. With it, React handles client-side routing.
## 14. Test the Nginx configuration
```bash theme={null}
sudo nginx -t
```
Expected:
```text theme={null}
syntax is ok
test is successful
```
Always test before reloading — invalid config can crash Nginx.
## 15. Restart Nginx
```bash theme={null}
sudo systemctl restart nginx
```
Visit `http://EC2_PUBLIC_IP` — the React app should load.
## 16. Configure the subdomain
Target: `react.vnta.agency`
In your DNS provider (Vercel DNS, Cloudflare, Namecheap, Route53), create:
| Type | Name | Value |
| ---- | ----- | --------------- |
| A | react | EC2\_PUBLIC\_IP |
Example:
| Type | Name | Value |
| ---- | ----- | ----------- |
| A | react | 13.60.19.93 |
Result: `react.vnta.agency → 13.60.19.93`
## 17. Verify DNS
```bash theme={null}
dig react.vnta.agency
# or
nslookup react.vnta.agency
```
Expected output should include `13.60.19.93`.
## 18. Configure Nginx for the domain
```bash theme={null}
sudo nano /etc/nginx/sites-available/default
```
```nginx theme={null}
server {
listen 80;
server_name react.vnta.agency;
root /var/www/react-app;
index index.html;
location / {
try_files $uri /index.html;
}
}
```
## 19. Install an SSL certificate
Install Certbot:
```bash theme={null}
sudo apt install certbot python3-certbot-nginx -y
```
Generate the certificate:
```bash theme={null}
sudo certbot --nginx -d react.vnta.agency
```
Certbot automatically:
* Validates domain ownership
* Creates the SSL certificate
* Updates the Nginx configuration
* Enables HTTPS redirect
## 20. Verify HTTPS
Visit `https://react.vnta.agency` — you should see the 🔒 secure indicator.
## 21. SSL auto-renewal
Check the timer:
```bash theme={null}
sudo systemctl status certbot.timer
```
Test renewal:
```bash theme={null}
sudo certbot renew --dry-run
```
Let's Encrypt certificates expire every 90 days, so auto-renewal is essential.
## 22. Security headers
Add inside the `server` block:
```nginx theme={null}
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy strict-origin always;
```
* **`X-Frame-Options: SAMEORIGIN`** — prevents clickjacking.
* **`X-Content-Type-Options: nosniff`** — prevents MIME type guessing.
* **`Referrer-Policy: strict-origin`** — improves privacy.
## 23. Enable compression
```nginx theme={null}
gzip on;
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml;
```
Reduces file sizes (e.g. `1 MB JS → ~200 KB`) for faster loads.
## 24. Browser caching
```nginx theme={null}
location /static/ {
expires 1y;
add_header Cache-Control "public";
}
```
Prevents re-downloading unchanged assets.
## 25. Log monitoring
Access logs:
```bash theme={null}
sudo tail -f /var/log/nginx/access.log
```
Shows visitors, pages requested, and IP addresses.
Error logs:
```bash theme={null}
sudo tail -f /var/log/nginx/error.log
```
Shows configuration issues, missing files, and permission problems.
## 26. Common troubleshooting
```bash theme={null}
sudo systemctl status nginx
sudo systemctl restart nginx
```
```bash theme={null}
sudo nginx -t
```
```bash theme={null}
dig react.vnta.agency
```
Verify the DNS A record.
Verify the domain points to the EC2 IP and port 80 is open, then retry:
```bash theme={null}
sudo certbot --nginx -d react.vnta.agency
```
```bash theme={null}
ls -la /var/www/react-app
sudo chown -R www-data:www-data /var/www/react-app
```
## Useful daily commands
```bash theme={null}
systemctl status nginx
systemctl restart nginx
systemctl reload nginx
nginx -t
df -h
free -h
top
htop
ss -tulpn
journalctl -u nginx
tail -f /var/log/nginx/error.log
```
## Final production checklist
* EC2 created
* Security groups configured
* Nginx installed
* React build generated
* Files uploaded
* Nginx configured
* React Router configured (`try_files`)
* DNS A record added
* SSL installed
* HTTPS enabled
* Security headers added
* Gzip enabled
* Browser cache enabled
* Logs monitored
* Auto SSL renewal working
* Nginx starts on boot
At this point the React application is running on AWS EC2 behind Nginx with a custom subdomain, HTTPS, basic security hardening, compression, caching, and monitoring support.