{"id":48510394,"url":"https://github.com/jonathan-vella/azure-postgresql-ha-workshop","last_synced_at":"2026-04-07T17:32:36.215Z","repository":{"id":318973807,"uuid":"1072864628","full_name":"jonathan-vella/azure-postgresql-ha-workshop","owner":"jonathan-vella","description":"Hands-on workshop for Azure PostgreSQL Flexible Server Zone-Redundant HA, failover testing, and database security","archived":false,"fork":false,"pushed_at":"2025-10-16T16:33:12.000Z","size":2106,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-16T22:25:25.537Z","etag":null,"topics":["azure","bicep","database","failover","high-availability","infrastructure-as-code","load-testing","payment-gateway","postgresql","security-training","workshop"],"latest_commit_sha":null,"homepage":"","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonathan-vella.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-09T10:11:01.000Z","updated_at":"2025-10-16T16:33:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jonathan-vella/azure-postgresql-ha-workshop","commit_stats":null,"previous_names":["jonathan-vella/azure-postgresql-ha-workshop"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jonathan-vella/azure-postgresql-ha-workshop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-vella%2Fazure-postgresql-ha-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-vella%2Fazure-postgresql-ha-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-vella%2Fazure-postgresql-ha-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-vella%2Fazure-postgresql-ha-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonathan-vella","download_url":"https://codeload.github.com/jonathan-vella/azure-postgresql-ha-workshop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonathan-vella%2Fazure-postgresql-ha-workshop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31522329,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","bicep","database","failover","high-availability","infrastructure-as-code","load-testing","payment-gateway","postgresql","security-training","workshop"],"created_at":"2026-04-07T17:32:36.030Z","updated_at":"2026-04-07T17:32:36.176Z","avatar_url":"https://github.com/jonathan-vella.png","language":"PowerShell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Azure PostgreSQL High Availability Workshop\n\n**Last Updated:** 2025-10-16\n\n\u003e **⚠️ SECURITY NOTICE**: This repository contains intentional security vulnerabilities for training purposes. DO NOT use in production!\n\n[![Documentation Version](https://img.shields.io/badge/docs-v1.1.0-blue.svg)](docs/)\n[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16-blue.svg)](https://www.postgresql.org/)\n[![Azure](https://img.shields.io/badge/Azure-Zone--Redundant%20HA-0089D6.svg)](https://azure.microsoft.com/en-us/products/postgresql/)\n[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n\n## 🎯 Purpose\n\nHands-on workshop for learning **Azure PostgreSQL Flexible Server Zone-Redundant High Availability**, failover testing, and database security concepts. Supports two workflows:\n\n1. **SAIF Security Demo** - Vulnerable payment gateway application for security training\n2. **High-Performance Load Testing** - 8000+ TPS PostgreSQL HA testing and validation\n\n## 📚 What You'll Learn\n\n- Deploy Zone-Redundant HA PostgreSQL Flexible Server\n- Measure RTO (Recovery Time Objective) and RPO (Recovery Point Objective)\n- **High-performance load testing** (8000+ TPS validated, 12,000+ TPS capable)\n- Test failover scenarios under sustained load\n- Identify and fix common security vulnerabilities\n- Implement secure database patterns\n- Performance monitoring with Azure Workbooks\n\n## 💰 Estimated Costs\n\n**Default Configuration** (as deployed):\n\n| Resource | Configuration | Estimated Cost/Hour | Monthly (730 hrs) |\n|----------|--------------|---------------------|-------------------|\n| PostgreSQL Flexible Server | Standard_D4ds_v5 (4 vCores, 16 GB RAM) | ~$0.28/hr | ~$205 |\n| PostgreSQL Zone-Redundant HA | Standby replica (same SKU) | ~$0.28/hr | ~$205 |\n| PostgreSQL Storage | 128 GB Premium SSD | ~$0.05/hr | ~$40 |\n| App Service Plan | P1v3 (2 vCPU, 8 GB RAM, Linux) | ~$0.26/hr | ~$190 |\n| Container Registry | Standard tier | ~$0.83/day | ~$25 |\n| Key Vault | Secrets storage + operations | ~$0.03/day | ~$1 |\n| Application Insights | Basic ingestion (Pay-as-you-go) | Variable | ~$10 |\n| **Total** | **Zone-Redundant HA Setup** | **~$0.90/hr** | **~$675/month** |\n\n💡 **Workshop duration: 2-4 hours** = **~$3.60 total cost**\n\n**High-Performance Configuration** (for 8K+ TPS testing):\n\n| Resource | Configuration | Estimated Cost/Hour | Monthly (730 hrs) |\n|----------|--------------|---------------------|-------------------|\n| PostgreSQL Flexible Server | Standard_D16ds_v5 (16 vCores, 64 GB RAM) | ~$1.15/hr | ~$840 |\n| PostgreSQL Zone-Redundant HA | Standby replica (same SKU) | ~$1.15/hr | ~$840 |\n| PostgreSQL Storage | 8 TB (P60 - 16K IOPS, 500 MB/s) | ~$1.10/hr | ~$800 |\n| App Service Plan | P1v3 (2 vCPU, 8 GB RAM, Linux) | ~$0.26/hr | ~$190 |\n| Load Testing (ACI) | 16 vCPU, 32 GB RAM (transient) | ~$0.80/hr | **$0** (test only) |\n| Supporting services | ACR, Key Vault, Insights | ~$0.04/hr | ~$35 |\n| **Total** | **High-Performance Setup** | **~$3.70/hr** | **~$2,705/month** |\n\n💡 **8K TPS Load Test duration: 5-10 minutes** = **~$0.62 test cost**\n\n\u003e 💸 **Cost Optimization Tips**:\n\u003e - **Development/Testing**: Use `-disableHighAvailability` flag to reduce costs by ~50% (single-zone deployment)\n\u003e - **Stop/Start**: Stop PostgreSQL server when not in use (stops compute costs, only pay for storage)\n\u003e - **Reserved Capacity**: Save up to 60% with 3-year reserved pricing for production workloads\n\u003e - **Burstable Tier**: Use Standard_B2s (~$0.05/hr) for non-production workloads\n\u003e - **Load Testing**: ACI is pay-per-second, delete after test completion to avoid charges\n\n## 🏗️ Architecture\n\nThis workshop uses **Azure Database for PostgreSQL Flexible Server** with **Zone-Redundant High Availability** to achieve:\n\n- **RPO = 0** (Zero data loss)\n- **RTO = 60-120 seconds** (Automatic failover)\n- **SLA = 99.99%** (Zone-redundant deployment)\n\n\u003e 📚 **Documentation**: This README provides a quick overview. For comprehensive documentation, see the [docs/](docs/) directory.\n\n## Architecture\n\n```mermaid\ngraph TB\n  subgraph Azure[\"☁️ Azure Cloud - Sweden Central\"]\n    subgraph Zone1[\"🔵 Availability Zone 1\"]\n      Web[\"🌐 Web App Service\u003cbr/\u003e(PHP/Apache)\u003cbr/\u003ePort 80\u003cbr/\u003e(Zonal)\"]\n      API[\"⚡ API App Service\u003cbr/\u003e(FastAPI)\u003cbr/\u003ePort 8000\u003cbr/\u003e(Zonal)\"]\n      PrimaryDB[\"🗄️ PostgreSQL Primary\u003cbr/\u003eStandard_D4ds_v5\u003cbr/\u003ePort 5432\u003cbr/\u003e128GB Premium SSD\"]\n      Monitor[\"📊 Application Insights\u003cbr/\u003e\u0026 Log Analytics\"]\n    end\n        \n    subgraph Zone2[\"🔷 Availability Zone 2\"]\n      StandbyDB[\"🗄️ PostgreSQL Standby\u003cbr/\u003eHot Standby (Read Replica)\u003cbr/\u003eSynchronous Replication\"]\n    end\n        \n    subgraph Support[\"🛠️ Supporting Services\"]\n      KeyVault[\"🔐 Azure Key Vault\u003cbr/\u003e(Secrets \u0026 Creds)\"]\n      ACR[\"📦 Azure Container Registry\u003cbr/\u003e(Docker Images)\"]\n      Backup[\"💾 Azure Backup\u003cbr/\u003e(7-day retention)\"]\n    end\n        \n    LoadGen[\"🔄 Load Generator\u003cbr/\u003e(Optional - ACI)\u003cbr/\u003e12,600+ TPS Capacity\"]\n  end\n    \n  Users[\"👥 End Users\u003cbr/\u003e(Web Browsers)\"]\n    \n  Users --\u003e|\"HTTPS (443)\"| Web\n  Web --\u003e|\"HTTP (8000)\"| API\n  API --\u003e|\"PostgreSQL (5432)\"| PrimaryDB\n  LoadGen -.-\u003e|\"Load Testing\"| API\n    \n  PrimaryDB ==\u003e|\"Synchronous Replication\u003cbr/\u003eRPO = 0 (Zero Data Loss)\"| StandbyDB\n  PrimaryDB --\u003e|\"Telemetry\"| Monitor\n  API --\u003e|\"Telemetry\"| Monitor\n  Web --\u003e|\"Telemetry\"| Monitor\n    \n  StandbyDB -.-\u003e|\"Automatic Failover\u003cbr/\u003eRTO: 60-120s\"| PrimaryDB\n    \n  PrimaryDB -.-\u003e|\"Get Secrets\"| KeyVault\n  API -.-\u003e|\"Get Secrets\"| KeyVault\n  Web -.-\u003e|\"Pull Images\"| ACR\n  API -.-\u003e|\"Pull Images\"| ACR\n  PrimaryDB -.-\u003e|\"Automated Backups\"| Backup\n    \n  classDef primary fill:#4A90E2,stroke:#2E5C8A,stroke-width:3px,color:#fff\n  classDef standby fill:#87CEEB,stroke:#4A90E2,stroke-width:2px,color:#000\n  classDef app fill:#52C41A,stroke:#389E0D,stroke-width:2px,color:#fff\n  classDef support fill:#FFA940,stroke:#D46B08,stroke-width:2px,color:#fff\n  classDef monitor fill:#722ED1,stroke:#531DAB,stroke-width:2px,color:#fff\n  classDef users fill:#F5222D,stroke:#A8071A,stroke-width:2px,color:#fff\n  classDef loadgen fill:#FA8C16,stroke:#D46B08,stroke-width:2px,color:#fff\n    \n  class PrimaryDB primary\n  class StandbyDB standby\n  class Web,API app\n  class KeyVault,ACR,Backup support\n  class Monitor monitor\n  class Users users\n  class LoadGen loadgen\n```\n\n**Architecture Highlights:**\n- **App Service is Zonal**: Web/API App Service is deployed in a single zone (Zone 1) for lowest latency\n- **Zone-Redundant HA for PostgreSQL**: Primary (Zone 1) and Standby (Zone 2) with synchronous replication\n- **RPO = 0**: Zero data loss with synchronous commit\n- **RTO = 60-120s**: Automatic failover between zones\n- **SLA = 99.99%**: Zone-redundant deployment guarantee\n- **Shared Services**: ACR, Key Vault, and monitoring are zone-redundant\n- **Load Testing**: Optional ACI deployment for 8K-12K TPS validation\n\n## Key Features\n\n### Payment Gateway Components\n- **Customers**: Customer account management\n- **Merchants**: Merchant/vendor profiles\n- **Payment Methods**: Credit cards, bank accounts, digital wallets\n- **Transactions**: Payment processing records with full audit trail\n- **Orders**: Order tracking and fulfillment\n\n### High Availability Features\n- **Zone-Redundant HA**: Primary and standby across availability zones\n- **Synchronous Replication**: Zero data loss guarantee\n- **Automatic Failover**: 60-120 second RTO\n- **Continuous Write Testing**: Validates failover with zero data loss\n- **Monitoring Dashboard**: Real-time HA status and metrics\n\n### Educational Vulnerabilities (Intentional)\n- ⚠️ SQL Injection in `/api/sqlversion` endpoint\n- ⚠️ Command Injection in `/api/curl` endpoint\n- ⚠️ Information Disclosure via `/api/printenv`\n- ⚠️ Hardcoded API keys\n- ⚠️ Permissive CORS policies\n- ⚠️ Exposed database connection strings\n\n## 🚀 Quick Start\n\n### Prerequisites\n- Azure subscription ([free trial available](https://azure.microsoft.com/free/))\n- Azure CLI installed and logged in\n- PowerShell 7+ or Azure Cloud Shell\n- Docker Desktop (optional, for local testing)\n\n\u003e 📖 For detailed prerequisites and setup instructions, see the [Deployment Guide](docs/deployment-guide.md).\n\n### Deploy (5 minutes)\n\n```powershell\n# Clone repository\ngit clone https://github.com/jonathan-vella/azure-postgresql-ha-workshop.git\ncd azure-postgresql-ha-workshop\n\n# Deploy infrastructure\n./scripts/Deploy-SAIF-PostgreSQL.ps1 -location swedencentral -autoApprove\n```\n\n[Full documentation →](docs/deployment-guide.md)\n\n### Deployment Options\n\n#### Option 1: Quick Deploy (Recommended for Workshop)\n```powershell\n# Deploy infrastructure\ncd infra\naz deployment group create \\\n  --resource-group rg-saif-pgsql-swc-01 \\\n  --template-file main.bicep \\\n  --parameters main.parameters.json\n\n# Initialize database\ncd ../scripts\n.\\Initialize-Database.ps1 `\n  -serverName \"psql-saifpg-XXXXXXXX\" `\n  -adminPassword \"YourSecurePassword\"\n\n# Build and deploy containers\naz acr build --registry \u003cyour-acr\u003e --image saif/api:latest --file api/Dockerfile ./api\naz acr build --registry \u003cyour-acr\u003e --image saif/web:latest --file web/Dockerfile ./web\n\n# Restart web apps to pull new images\naz webapp restart --name app-saifpg-api-XXXXXXXX --resource-group rg-saif-pgsql-swc-01\naz webapp restart --name app-saifpg-web-XXXXXXXX --resource-group rg-saif-pgsql-swc-01\n```\n\n#### Option 2: Local Development\n```powershell\n# Start local services\ndocker-compose up -d\n\n# Initialize database\ndocker exec -it saif-postgres psql -U saifadmin -d saifdb -f /docker-entrypoint-initdb.d/init-db.sql\n\n# Access application\n# Web: http://localhost:8080\n# API: http://localhost:8000\n```\n\n\u003e 📖 For comprehensive deployment options and troubleshooting, see [TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md).\n\n### Database Initialization\n\nThe database requires the **uuid-ossp** extension for transaction IDs. On Azure PostgreSQL Flexible Server, this must be explicitly enabled:\n\n```powershell\n# Enable uuid-ossp extension\naz postgres flexible-server parameter set \\\n  --resource-group rg-saif-pgsql-swc-01 \\\n  --server-name psql-saifpg-XXXXXXXX \\\n  --name azure.extensions \\\n  --value \"UUID-OSSP\"\n\n# Run initialization script\ncd scripts\n.\\Initialize-Database.ps1 `\n  -serverName \"psql-saifpg-XXXXXXXX.postgres.database.azure.com\" `\n  -adminPassword \"YourPassword\"\n```\n\n\u003e 📖 For detailed database initialization procedures, see [Container Initialization Guide](docs/guides/container-initialization-guide.md).\n\n## Database Schema\n\n### Payment Gateway Schema\n```sql\n-- Customers\nCREATE TABLE customers (\n    customer_id SERIAL PRIMARY KEY,\n    email VARCHAR(255) UNIQUE NOT NULL,\n    first_name VARCHAR(100),\n    last_name VARCHAR(100),\n    phone VARCHAR(20),\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- Merchants\nCREATE TABLE merchants (\n    merchant_id SERIAL PRIMARY KEY,\n    merchant_name VARCHAR(255) NOT NULL,\n    merchant_code VARCHAR(50) UNIQUE NOT NULL,\n    api_key VARCHAR(255),\n    status VARCHAR(20) DEFAULT 'active'\n);\n\n-- Transactions\nCREATE TABLE transactions (\n    transaction_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n    customer_id INTEGER REFERENCES customers(customer_id),\n    merchant_id INTEGER REFERENCES merchants(merchant_id),\n    amount DECIMAL(10,2) NOT NULL,\n    currency VARCHAR(3) DEFAULT 'USD',\n    status VARCHAR(20),\n    transaction_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n```\n\n## API Endpoints\n\n### Payment Gateway APIs\n- `POST /api/payments/process` - Process payment transaction\n- `GET /api/payments/{transaction_id}` - Get transaction status\n- `GET /api/payments/customer/{customer_id}` - Get customer transactions\n- `POST /api/customers/create` - Create customer account\n\n### Diagnostic APIs (Vulnerable by Design)\n- `GET /api/healthcheck` - Service health status\n- `GET /api/ip` - Server IP information\n- `GET /api/sqlversion` - Database version ⚠️ SQL Injection vulnerability\n- `GET /api/curl?url=\u003curl\u003e` - Fetch URL ⚠️ SSRF/Command injection\n- `GET /api/printenv` - Environment variables ⚠️ Information disclosure\n\n## 📊 Performance Benchmarks\n\n### App Service Load Testing (Current)\n- **Validated TPS**: **1,000-2,000+ TPS per instance** (immediate App Insights logging)\n- **Scaling**: Supports multiple App Service instances for higher throughput\n- **Response Time**: Immediate telemetry (no Log Analytics delays)\n- **Infrastructure**: P0v3 App Service Plan (standard) to P1v3 (upgrade for higher TPS)\n- **Monitoring**: Real-time HTTP status endpoints + Application Insights dashboard\n\n### Failover Testing Performance (RTO/RPO)\n- **Measured RTO**: **16-25 seconds** (Zone-Redundant HA automatic failover)\n- **Measured RPO**: **0 transactions** (zero data loss with synchronous replication)\n- **Test Method**: App Service load test + manual failover trigger + Measure-Failover-RTO-RPO.ps1\n- **Success Rate**: 100% data consistency (all transactions persisted before failover)\n- **Monitoring**: Real-time probes (1-second intervals), detailed CSV reports\n\n\u003e 📖 **Quick Start**: See [Load Testing Guide](docs/load-testing-guide.md) for complete deployment and monitoring\n\n### Legacy Benchmarks (ACI - Archived)\n- **8000-12,600+ TPS** (Azure Container Instances, archived approach)\n- **Succeeded**: October 10, 2025 test with D16ds_v5 + P60 storage\n- **Reference**: [Archive benchmarks](archive/) for historical context\n\n### Load Testing \u0026 Failover Testing\n\nThe workshop includes **two testing approaches**:\n\n#### Option 1: App Service Load Testing ⭐ **RECOMMENDED - IMMEDIATE MONITORING**\n```powershell\n# Deploy load generator to App Service\ncd scripts/loadtesting\n.\\Deploy-LoadGenerator-AppService.ps1 `\n  -Action \"Deploy\" `\n  -ResourceGroup \"rg-pgv2-usc01\" `\n  -AppServiceName \"app-loadgen\" `\n  -PostgreSQLServer \"pg-cus.postgres.database.azure.com\" `\n  -DatabaseName \"saifdb\" `\n  -AdminUsername \"jonathan\"\n\n# Start load test via HTTP API\n$url = \"https://app-loadgen.azurewebsites.net/start\"\ncurl -X POST $url | ConvertFrom-Json\n\n# Monitor in real-time\n.\\Monitor-AppService-Logs.ps1 -ResourceGroup \"rg-pgv2-usc01\" -AppServiceName \"app-loadgen\"\n\n# Check status\ncurl https://app-loadgen.azurewebsites.net/status | ConvertFrom-Json | Format-List\n```\n\n**Use Case**: Production-grade load testing with immediate Application Insights monitoring  \n**Throughput**: **1,000-2,000+ TPS** per App Service instance (scalable)  \n**Features**:\n- HTTP API endpoints (`/start`, `/status`, `/health`, `/logs`)\n- Real-time Application Insights telemetry (no delays)\n- Container-based .NET 8.0 application\n- Automatic database transaction logging\n- Easy scaling via App Service plan upgrade\n\n\u003e 📖 **Complete Guide**: [Load Testing Guide](docs/load-testing-guide.md) - Comprehensive deployment \u0026 monitoring\n\n#### Option 2: RTO/RPO Failover Testing ⭐ **MEASURE RECOVERY METRICS**\n```powershell\n# Start failover measurement with running load test\ncd scripts/loadtesting\n.\\Measure-Failover-RTO-RPO.ps1 `\n  -AppServiceUrl \"https://app-loadgen-6wuso.azurewebsites.net\" `\n  -ResourceGroup \"rg-pgv2-usc01\" `\n  -ServerName \"pg-cus\" `\n  -DatabaseName \"saifdb\" `\n  -AdminUsername \"jonathan\" `\n  -MaxMonitoringSeconds 90\n\n# Then trigger manual failover in Azure Portal:\n# 1. PostgreSQL Flexible Server \u003e High Availability blade\n# 2. Click \"Forced failover\"\n# 3. Confirm action\n# Script will measure RTO and RPO\n```\n\n**Use Case**: Measure recovery time and data loss during failover  \n**RTO**: 16-25 seconds (measured in October 2025)  \n**RPO**: 0 transactions (zero data loss with synchronous replication)  \n**Features**:\n- Real-time monitoring during failover\n- Connection loss detection (1-second probes)\n- Database transaction count verification\n- TPS recovery tracking\n- CSV report generation with detailed metrics\n\n\u003e 📖 **Complete Guide**: [Failover Testing Guide](docs/failover-testing-guide.md) - RTO/RPO measurement procedures\n\u003e 📖 **Cheat Sheet**: [Load Testing Cheat Sheet](docs/load-testing-cheat-sheet.md) - Quick commands reference\n\n## Security Considerations\n\n### Production Hardening (Not Included)\nThis is an **educational environment** with intentional vulnerabilities. For production:\n\n1. **Remove SQL Injection**: Use parameterized queries everywhere\n2. **Implement Input Validation**: Sanitize all user inputs\n3. **Secure Environment Variables**: Use Key Vault exclusively\n4. **Network Isolation**: Use VNet integration + Private Endpoints\n5. **Authentication**: Implement Entra ID authentication\n6. **Audit Logging**: Enable PostgreSQL audit extension\n\n## Project Structure\n\n```\nazure-postgresql-ha-workshop/\n├── 📁 infra/                          # Infrastructure as Code (Bicep templates)\n│   ├── main.bicep                     # Main deployment template\n│   ├── main.parameters.json           # Deployment parameters\n│   └── modules/\n│       ├── database/\n│       │   └── postgresql.bicep       # PostgreSQL HA module\n│       └── keyvault/\n│           └── keyvault.bicep         # Key Vault secrets management\n│\n├── 📁 database/                       # Database initialization scripts\n│   ├── init-db.sql                    # Schema creation (customers, merchants, transactions)\n│   ├── enable-uuid.sql                # UUID extension setup\n│   ├── cleanup-db.sql                 # Database cleanup utilities\n│   └── README.md                      # Database documentation\n│\n├── 📁 web/                            # SAIF PHP Web Application (security demos)\n├── 📁 api/                            # SAIF Python FastAPI (security demos)\n├── 📄 docker-compose.yml              # Local SAIF development environment\n│\n├── 📁 scripts/                        # Operational scripts\n│   ├── 🚀 Deploy-SAIF-PostgreSQL.ps1  # Full infrastructure deployment\n│   ├── 🚀 Quick-Deploy-SAIF.ps1       # Simplified deployment wrapper\n│   ├── 🌐 Rebuild-SAIF-Containers.ps1 # SAIF app container rebuild\n│   ├── 🌐 Test-SAIFLocal.ps1          # Local SAIF testing\n│   ├── 💾 Initialize-Database.ps1     # Database initialization\n│   ├── 📖 README.md                    # Scripts documentation\n│   │\n│   ├── 📁 loadtesting/                # Load testing \u0026 failover testing scripts (current)\n│   │   ├── 🧪 Program.cs              # .NET 8.0 load generator web app\n│   │   ├── 🧪 Dockerfile              # Multi-stage container build\n│   │   ├── � Deploy-LoadGenerator-AppService.ps1 # Deploy to App Service\n│   │   ├── � Monitor-AppService-Logs.ps1         # Stream container logs\n│   │   ├── 🔄 Measure-Failover-RTO-RPO.ps1       # RTO/RPO measurement\n│   │   ├── � LoadGenerator-Config.ps1  # Centralized configuration\n│   │   ├── 📖 README.md                 # Load testing documentation (v1.0.0)\n│   │   └── archive/                     # Archived testing approaches\n│   │\n│   ├── utils/\n│   │   └── Build-SAIF-Containers.ps1   # SAIF container build utility\n│   └── archive/                        # Archived scripts (historical)\n│\n├── 📁 azure-workbooks/                # Azure Portal monitoring\n│   ├── PostgreSQL-HA-Performance-Workbook.json # Pre-configured workbook (6 charts)\n│   └── IMPORT-GUIDE.md                         # 30-second import guide\n│\n├── 📁 docs/                           # Documentation (v1.1.0+)\n│   ├── architecture.md                # System architecture \u0026 design (v2.0.0)\n│   ├── CHANGELOG.md                   # Documentation version history (v2.2.0)\n│   ├── deployment-guide.md            # Complete deployment guide (v2.1.0)\n│   ├── failover-testing-guide.md      # RTO/RPO measurement procedures (v1.0.0)\n│   ├── load-testing-guide.md          # App Service load testing guide (v1.1.0)\n│   ├── load-testing-cheat-sheet.md    # Quick reference commands (v1.0.0)\n│   ├── README.md                      # Documentation index\n│   ├── VERSIONING-UPDATE-PLAN.md      # Semantic versioning migration plan\n│   ├── VERSIONING-UPDATE-SUMMARY.md   # Implementation summary\n│   │\n│   └── archive/ (v1.0.0 docs - deprecated)\n│       ├── index.md, quick-reference.md, checklist.md\n│       ├── guides/ (container, initialization procedures)\n│       └── architecture/ (detailed implementations)\n│\n└── 📁 archive/                        # Archived files (historical reference)\n    ├── deprecated-approaches/         # Old testing methods\n    ├── documentation/                 # Development diaries\n    ├── duplicates/                    # Removed duplicates\n    ├── generated-outputs/             # Test artifacts\n    └── README.md                      # Archive documentation\n```\n\n## 📚 Documentation\n\n**[📖 Complete Documentation Index](docs/README.md)** - Start here for all documentation\n\n### 🚀 Quick Start Guides\n\n- **[📘 Deployment Guide](docs/deployment-guide.md)** - Complete step-by-step deployment\n- **[🧪 Testing Guide](docs/testing-guide.md)** - Load testing (8K TPS) + Failover testing\n- **[🏗️ Architecture](docs/architecture.md)** - System design and components\n- **[🔥 Troubleshooting](docs/TROUBLESHOOTING.md)** - Common issues \u0026 solutions\n\n### 🧪 Testing \u0026 Monitoring\n\n- **[🧪 Testing Guide](docs/testing-guide.md)** - Complete load testing (8K TPS) + failover testing\n- **[📊 Azure Workbook Import](azure-workbooks/IMPORT-GUIDE.md)** - 30-second performance dashboard setup\n- **[📖 RTO Measurement](scripts/CONNECTION-RTO-GUIDE.md)** - Connection RTO testing guide\n- **[📖 Failover Monitoring](scripts/MONITOR-FAILOVER-GUIDE.md)** - Monitor failover events\n\n### 🗄️ Database \u0026 SAIF Application\n\n- **[🗄️ Database Initialization](archive/docs-v1.0.0/guides/container-initialization-guide.md)** - Setup procedures (archived)\n- **[🐳 Container Build Guide](archive/docs-v1.0.0/guides/BUILD-CONTAINERS-GUIDE.md)** - SAIF app container builds (archived)\n\n### 📐 Architecture \u0026 Deep Dive\n\n- **[🏗️ Architecture](docs/architecture.md)** - System design \u0026 components\n- **[💻 Implementation Details](archive/docs-v1.0.0/architecture/IMPLEMENTATION-COMPLETE.md)** - Technical deep dive (archived)\n- **[📝 Changelog](docs/CHANGELOG.md)** - Version history\n\n\u003e 💡 **Tip**: Having issues? Check [TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) first!\n\n## 🤝 Contributing\n\nContributions welcome! Please read our [Code of Conduct](CODE_OF_CONDUCT.md) before contributing.\n\n### How to Contribute:\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## 📄 License\n\nMIT License - See [LICENSE](LICENSE) for details.\n\nCopyright (c) 2025 Jonathan Vella\n\n## ⚠️ Security Disclaimer\n\nThis project contains **intentional security vulnerabilities** for educational purposes. See [SECURITY.md](SECURITY.md) for details.\n\n**DO NOT**:\n- ❌ Deploy this in production environments\n- ❌ Use these patterns in real applications\n- ❌ Expose these applications to the public internet\n\n## 🙏 Acknowledgments\n\nBuilt for Microsoft Azure training workshops and hackathons.\n\n## 📚 References\n\n- [Azure PostgreSQL Flexible Server HA](https://learn.microsoft.com/azure/reliability/reliability-postgresql-flexible-server)\n- [Azure Well-Architected Framework](https://learn.microsoft.com/azure/architecture/framework/)\n- [PostgreSQL Performance Tuning](https://www.postgresql.org/docs/current/performance-tips.html)\n- [OWASP Top 10](https://owasp.org/www-project-top-ten/) - Security vulnerability reference\n\n---\n\n## 📦 Repository Organization\n\nThis repository was reorganized on **October 10, 2025** (v2.0.0) to streamline workflows and improve maintainability:\n\n- **Core operational files**: Infrastructure, deployment, load testing, monitoring (35 files)\n- **Archived files**: Historical artifacts preserved in `/archive/` (44 files)\n- **Two workflows supported**: SAIF security demos + High-performance load testing\n\nSee [REORGANIZATION-SUMMARY.md](REORGANIZATION-SUMMARY.md) for complete reorganization details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathan-vella%2Fazure-postgresql-ha-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonathan-vella%2Fazure-postgresql-ha-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonathan-vella%2Fazure-postgresql-ha-workshop/lists"}