Skip to content

Infrastructure Architecture ​

Vulcan runs on Azure, deployed to Azure Kubernetes Service (AKS) in Sweden Central for GDPR compliance.

Resource Names ​

Actual Production Resources

Some resources have non-standard names due to Azure global uniqueness requirements:

  • Key Vault: vulcan-kv-se-prod (not vulcan-kv-prod)
  • Storage: vulcanstprod (not vulcanstorageprod)

Azure Resources ​

Compute ​

ResourceNameSKUPurpose
AKS Clustervulcan-aks-prodStandard_D4s_v3 (3-10 nodes)Kubernetes 1.32 with Cilium CNI
Container RegistryvulcanacrprodStandardDocker images

Data ​

ResourceNameSKUPurpose
PostgreSQL Flexible (core)vulcan-pg-core-prodStandard_D4s_v3Core databases (coresetup, contracts, documents)
PostgreSQL Flexible (ops)vulcan-pg-ops-prodStandard_D8s_v3Ops databases with pgvector (leads, quotation, projects, invoicing, planning, ai)
Redis Cachevulcan-redis-prodPremium P1Caching, sessions
Storage AccountvulcanstprodStandard_LRSBlob storage

AI ​

ResourceNameModelPurpose
Azure OpenAIvulcan-openai-prodGPT-4oQuote evaluation, contract analysis
Azure OpenAIvulcan-openai-prodtext-embedding-3-largeDocument embeddings (1536 dim)
Azure OpenAIvulcan-openai-prodwhisperVoice transcription
Content Safetyvulcan-content-safety-prod-AI guardrails (jailbreak, PII, moderation)

Messaging ​

ResourceNameSKUPurpose
Service Busvulcan-sb-prodPremiumMassTransit async messaging

Security ​

ResourceNamePurpose
Key Vaultvulcan-kv-se-prodSecrets management (RBAC enabled)
Application Insights-Monitoring
Log Analytics-Centralized logging

Database Distribution ​

PostgreSQL Flexible Servers
β”œβ”€β”€ vulcan-pg-core-prod (Standard_D4s_v3, 64GB)
β”‚   β”œβ”€β”€ coresetup     β†’ vulcan-be-coresetup
β”‚   β”œβ”€β”€ contracts     β†’ vulcan-be-contracts
β”‚   └── documents     β†’ vulcan-be-documents
β”‚
└── vulcan-pg-ops-prod (Standard_D8s_v3, 128GB, pgvector)
    β”œβ”€β”€ leads         β†’ vulcan-be-leads
    β”œβ”€β”€ quotation     β†’ vulcan-be-quotation
    β”œβ”€β”€ projects      β†’ vulcan-be-projects
    β”œβ”€β”€ invoicing     β†’ vulcan-be-invoicing
    β”œβ”€β”€ planning      β†’ vulcan-be-planning
    └── ai            β†’ vulcan-be-ai (vector embeddings)

Architecture Diagram ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Azure Region: Sweden Central              β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚              Azure Kubernetes Service (K8s 1.32)           β”‚ β”‚
β”‚  β”‚                        Cilium CNI                          β”‚ β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚ β”‚
β”‚  β”‚  β”‚  vulcan-be- β”‚ β”‚  vulcan-be- β”‚ β”‚  vulcan-be- β”‚          β”‚ β”‚
β”‚  β”‚  β”‚  coresetup  β”‚ β”‚    leads    β”‚ β”‚  quotation  β”‚   ...    β”‚ β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜          β”‚ β”‚
β”‚  β”‚         β”‚               β”‚               β”‚                  β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚            β”‚               β”‚               β”‚                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚              PostgreSQL Flexible Servers                    β”‚ β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚ β”‚
β”‚  β”‚  β”‚  vulcan-pg-core     β”‚  β”‚   vulcan-pg-ops     β”‚          β”‚ β”‚
β”‚  β”‚  β”‚  (D4s_v3, 64GB)     β”‚  β”‚  (D8s_v3, 128GB)    β”‚          β”‚ β”‚
β”‚  β”‚  β”‚  coresetup          β”‚  β”‚  leads, quotation   β”‚          β”‚ β”‚
β”‚  β”‚  β”‚  contracts          β”‚  β”‚  projects, invoicingβ”‚          β”‚ β”‚
β”‚  β”‚  β”‚  documents          β”‚  β”‚  planning, ai       β”‚          β”‚ β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚   Redis Cache   β”‚  β”‚  Service Bus    β”‚  β”‚   Key Vault     β”‚ β”‚
β”‚  β”‚   (Premium P1)  β”‚  β”‚   (Premium)     β”‚  β”‚   (RBAC)        β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚                      Azure OpenAI                            β”‚β”‚
β”‚  β”‚  GPT-4o β”‚ text-embedding-3-large β”‚ whisper                  β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Kubernetes Architecture ​

yaml
# Cluster configuration
cluster:
  name: vulcan-aks-prod
  version: "1.32"
  network_plugin: azure
  network_dataplane: cilium

# Namespace structure
namespaces:
  - vulcan-staging    # Staging environment
  - vulcan-prod       # Production environment

# Per namespace deployments
deployments:
  - vulcan-web
  - vulcan-be-coresetup
  - vulcan-be-leads
  - vulcan-be-quotation
  - vulcan-be-contracts
  - vulcan-be-projects
  - vulcan-be-invoicing
  - vulcan-be-documents
  - vulcan-be-ai
  - vulcan-be-planning

services:
  - ClusterIP for internal communication
  - LoadBalancer for public endpoints

ingress:
  - Nginx Ingress Controller
  - TLS termination
  - Path-based routing

Key Vault Secrets ​

SecretPurpose
pg-admin-passwordPostgreSQL admin password
servicebus-connectionService Bus connection string
redis-connectionRedis connection string
storage-connectionStorage account connection string
openai-api-keyAzure OpenAI API key
openai-endpointAzure OpenAI endpoint URL

Deployment Pipeline ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Push      β”‚    β”‚   GitLab CI  β”‚    β”‚    AKS       β”‚
β”‚  to Branch   β”‚ β†’  β”‚   Pipeline   β”‚ β†’  β”‚  Deployment  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Pipeline Stages:
1. Build      - Compile code, run tests
2. Docker     - Build and push image to ACR
3. Deploy     - Update Kubernetes deployment
4. Verify     - Health check

Environment Configuration ​

Staging ​

URL: https://staging.hack.aceve.cloud
Branch: develop
Deployment: Automatic after tests pass
Approval: None required

Production ​

URL: https://vulcan.aceve.cloud
Branch: main
Deployment: Manual trigger
Approval: Required

Infrastructure as Code ​

vulcan-infrastructure/
β”œβ”€β”€ terraform/
β”‚   β”œβ”€β”€ modules/
β”‚   β”‚   β”œβ”€β”€ aks/
β”‚   β”‚   β”œβ”€β”€ postgresql/
β”‚   β”‚   β”œβ”€β”€ redis/
β”‚   β”‚   β”œβ”€β”€ keyvault/
β”‚   β”‚   └── openai/
β”‚   β”œβ”€β”€ environments/
β”‚   β”‚   β”œβ”€β”€ staging/
β”‚   β”‚   └── production/
β”‚   └── main.tf
β”œβ”€β”€ kubernetes/
β”‚   β”œβ”€β”€ base/
β”‚   β”‚   β”œβ”€β”€ deployments/
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   └── ingress/
β”‚   └── overlays/
β”‚       β”œβ”€β”€ staging/
β”‚       └── production/
└── scripts/
    β”œβ”€β”€ deploy.sh
    └── rollback.sh

Observability ​

OpenTelemetry ​

All services export telemetry via OpenTelemetry OTLP to Datadog Agent:

  • Traces: Distributed tracing with ASP.NET Core, HTTP client, and EF Core instrumentation
  • Metrics: Runtime, ASP.NET Core, and custom application metrics
  • Logs: Structured logging via OpenTelemetry logging provider

Datadog Agent ​

  • Deployed as DaemonSet in AKS (datadog namespace)
  • OTLP receiver on http://datadog-agent.datadog:4317 (gRPC)
  • Automatic correlation of traces, metrics, and logs

Configuration ​

Services are configured via environment variables:

yaml
env:
  - name: OTEL_SERVICE_NAME
    value: "vulcan-be-<service>"
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: "http://datadog-agent.datadog:4317"
  - name: OTEL_EXPORTER_OTLP_PROTOCOL
    value: "grpc"
  - name: OTEL_RESOURCE_ATTRIBUTES
    value: "deployment.environment=prod,service.namespace=vulcan,team=platform"

Dashboards ​

  • Datadog APM for traces and service maps
  • Datadog Logs for centralized log aggregation
  • Datadog Dashboards for custom metrics visualization

Security ​

Network ​

  • AKS with Cilium CNI
  • Network policies
  • Private endpoints for PaaS (planned)

Identity ​

  • Azure AD integration
  • Managed Identity for services
  • RBAC for resources

Secrets ​

  • Key Vault for all secrets
  • No secrets in code or config
  • Automatic rotation where supported

Disaster Recovery ​

ComponentRPORTOStrategy
Database5 min1 hourPoint-in-time restore (35-day retention)
Storage00GRS replication
AKSN/A30 minMulti-replica deployments

Cost Estimation ​

ResourceMonthly Cost
AKS (3 nodes)~$600
PostgreSQL (2 servers)~$1,000
Azure OpenAI~$300-800
Service Bus Premium~$400
Redis Premium~$500
Storage~$100
Other (KV, ACR, etc.)~$100
Total~$3,000-3,500

Built with VitePress | v1.2.0 | πŸš€ Week One Sprint