Last Updated: December 2, 2025
Purpose: Define target-state environment architecture for development, testing, staging, and production.
| Environment | Purpose | URLs | Database | Data Policy |
|---|---|---|---|---|
| Development | Local coding, feature dev | lookup.bualum.dev:3000, champions.bualum.dev:3000 |
Local PG (isolated) | Seeded fixtures |
| Test | Automated test suite | localhost | Local PG (ephemeral) | Fixtures per run |
| Staging | Pre-prod validation, UAT | staging-lookup.bualum.co, staging-champions.bualum.co |
Heroku PG (isolated) | Scrubbed prod copy or seeds |
| Production | Live users | lookup.bualum.co, champions.bualum.co |
Heroku PG | Real data |
| Aspect | Configuration |
|---|---|
| Purpose | Local feature development, debugging |
| Who Uses | Developer(s) |
| URLs | lookup.bualum.dev:3000, champions.bualum.dev:3000 |
| Database | alumni_lookup_development (local PostgreSQL) |
| Migrations | Run manually (rails db:migrate) |
| Data | Seeds + fixtures, no real PII |
| Service | Behavior | Notes |
|---|---|---|
| Letter Opener | Opens in browser, no network | |
| Storage | Local disk | storage/ directory |
| CRM | Disabled | No Salesforce calls |
| Logging | Rails logger | log/development.log |
| Monitoring | None | Use byebug/pry |
| Aspect | Configuration |
|---|---|
| Purpose | Automated test suite execution |
| Who Uses | CI system, developers |
| URLs | N/A (request specs use test host) |
| Database | alumni_lookup_test (local PostgreSQL, transactional) |
| Migrations | Auto via rails test |
| Data | Fixtures only, reset per test |
| Service | Behavior | Notes |
|---|---|---|
| Test adapter | Emails in ActionMailer::Base.deliveries |
|
| Storage | Temp disk | tmp/storage/ |
| CRM | Disabled | Stubbed/mocked if needed |
| Logging | STDERR | Deprecations only |
| Monitoring | Test output | Assertions and failures |
| Aspect | Configuration |
|---|---|
| Purpose | Pre-production validation, UAT, smoke tests |
| Who Uses | Developer, QA, stakeholders for review |
| URLs | staging-lookup.bualum.co, staging-champions.bualum.co |
| Database | Separate Heroku Postgres (not shared with prod) |
| Migrations | Auto on deploy (CI pipeline) |
| Data | See Data Strategy |
| Service | Behavior | Notes |
|---|---|---|
| Mailgun Sandbox OR restricted recipients | No real user emails | |
| Storage | Cloudinary (separate folder/namespace) | Keep isolated from prod |
| CRM | Disabled or sandbox | No writes to prod Salesforce |
| Logging | Heroku Logs | Standard logging |
| Monitoring | Optional APM | Heroku metrics sufficient |
Choose ONE approach:
| Approach | Pros | Cons |
|---|---|---|
| Seeded Data | Fast, no PII risk, repeatable | May miss edge cases |
| Scrubbed Prod Copy | Realistic, catches data issues | Complex, needs PII scrubbing |
| Fresh Each Deploy | Clean slate | No historical data patterns |
Recommendation: Start with seeded data using the existing fixtures. Add scrubbed prod copy only if needed for specific testing.
| Aspect | Configuration |
|---|---|
| Purpose | Serve live users |
| Who Uses | Alumni staff, champions |
| URLs | lookup.bualum.co, champions.bualum.co |
| Database | Heroku Postgres (production tier) |
| Migrations | Via CI after staging validation |
| Data | Real alumni data |
| Service | Behavior | Notes |
|---|---|---|
| Mailgun (live) | Real delivery | |
| Storage | Cloudinary (live) | Production images |
| CRM | Export-only | Contact ID in CSV exports |
| Logging | Heroku Logs + optional APM | Consider Papertrail/Logentries |
| Monitoring | Heroku Metrics | Consider New Relic/Scout |
Architecture: Separate Heroku app with dedicated database, production-like but smaller tier for cost savings.
┌─────────────────────────────────────────────────────────────┐
│ Staging Setup (Light Usage) │
├─────────────────────────────────────────────────────────────┤
│ App: alumni-lookup-staging │
│ Dynos: 1x Basic ($7/mo) │
│ Database: Mini ($5/mo) or Essential 0 (~$5/mo) │
│ Domains: staging-lookup.bualum.co, staging-champions... │
│ SSL: Heroku ACM (free) │
├─────────────────────────────────────────────────────────────┤
│ Estimated Cost: ~$12/month │
│ Usage: Sanity testing before production deploys │
└─────────────────────────────────────────────────────────────┘
| Pros | Cons |
|---|---|
| ✅ Same stack as production | 💰 ~$12/month cost |
| ✅ Tests both subdomains | ⚙️ Additional config to maintain |
| ✅ Can run migrations before prod | 🔄 Need to keep in sync |
| ✅ Supports role-based testing | |
| ✅ Sufficient for sanity testing |
Database Options:
| Plan | Cost | Rows | Best For |
|---|---|---|---|
| Mini | $5/mo | 10K rows | Small datasets, demo data |
| Basic | $9/mo | 10M rows | Larger fixture sets |
Architecture: Use Heroku Review Apps for PR-based staging (ephemeral, not persistent).
┌─────────────────────────────────────────────────────────────┐
│ Lightweight Staging │
├─────────────────────────────────────────────────────────────┤
│ App: Review Apps per PR │
│ Dynos: Auto-provisioned, auto-destroyed │
│ Database: Ephemeral (built from seed on each PR) │
│ Domains: Auto-generated (*.herokuapp.com) │
├─────────────────────────────────────────────────────────────┤
│ Estimated Cost: $0-5/month (pay per hour when active) │
└─────────────────────────────────────────────────────────────┘
| Pros | Cons |
|---|---|
| ✅ Near-zero cost when idle | ❌ No persistent staging |
| ✅ Fresh environment per PR | ❌ Custom domains harder |
| ✅ Auto cleanup | ❌ Less production-like |
| ✅ Good for PR review | ❌ Can’t test subdomain routing easily |
Architecture: True staging for final validation + Review Apps for PR preview.
┌─────────────────────────────────────────────────────────────┐
│ Hybrid Staging │
├─────────────────────────────────────────────────────────────┤
│ Persistent Staging: alumni-lookup-staging │
│ - Deploy on merge to main │
│ - Stable URL for stakeholders │
│ - Full two-domain testing │
│ │
│ Review Apps: Per-PR (optional, when needed) │
│ - Enable for specific PRs │
│ - Quick feedback loop │
├─────────────────────────────────────────────────────────────┤
│ Estimated Cost: $12-16/month + occasional Review Apps │
└─────────────────────────────────────────────────────────────┘
Based on PERMISSIONS_MATRIX.md, staging must support testing these roles:
| Role | Test Requirements |
|---|---|
| Admin | Full settings access, user management, imports, cache clearing |
| Staff | Search, view alumni, engagement stats, champion management (read/edit, no delete) |
| Anonymous | Redirect to login on all protected routes |
| Role | Test Requirements |
|---|---|
| Champion | Access champion portal features (when built) |
| City Leader (CLC) | Regional champion management (when built) |
Create these fixture/seed users in staging:
# Suggested staging users
staging_admin:
email: staging-admin@bualum.co
role: admin
staging_staff:
email: staging-staff@bualum.co
role: staff
staging_champion:
email: staging-champion@example.com
role: champion # Future
Include in staging smoke tests:
/settings/users/settingsWhy:
Two-Domain Architecture: Your app serves lookup.bualum.co and champions.bualum.co. A persistent staging app with staging-lookup.bualum.co and staging-champions.bualum.co tests the full subdomain routing.
Role-Based Testing: With Admin/Staff/Champion roles defined, you need a stable environment to verify permission boundaries before production.
Solo Developer: With no team to catch issues, staging acts as your safety net. ~$12/month is cheap insurance against production bugs.
Light Usage: Since you’re primarily doing sanity testing, a Basic dyno handles the load fine.
Setup Cost:
| Component | Monthly Cost |
|---|---|
| Basic Dyno | $7 |
| Mini Postgres | $5 |
| Total | ~$12 |
Comparison with Production:
| Environment | Dyno | Database | Monthly Cost |
|---|---|---|---|
| Production | 2x Web (~$0.069/hr) | Essential 0 (~$0.007/hr) | ~$55-60 |
| Staging | Basic ($7 flat) | Mini ($5 flat) | ~$12 |