Skip to content

Cloud-Native Mindset

This document defines ConnectSoft's cloud-native architecture principles. It is written for architects and engineers building systems for Azure Kubernetes and cloud infrastructure.

Everything runs as containers with Infrastructure-as-Code, autoscaling, multi-tenant-safe design, and observability built-in. Cloud-native is not optional—it's the default for all ConnectSoft-generated systems.

Important

All systems must be multi-tenant-safe by design, containerized, and deployable via Infrastructure-as-Code. Autoscaling and observability are not afterthoughts—they're built into every template.

Principles We Follow

ConnectSoft follows cloud-native principles inspired by the 12-Factor App methodology:

Stateless Services

  • No local state - Services don't store state in memory or local files
  • State in external stores - Databases, caches, object storage
  • Session state externalized - Sessions stored in Redis or database

Configuration from Environment

  • Environment variables - Configuration via environment variables
  • External config service - Use ConnectSoft Config Platform for runtime config
  • Secrets in Key Vault - Never hardcode secrets, use Azure Key Vault

Logs as Streams

  • Structured logging - JSON logs with correlation IDs
  • Log aggregation - Logs sent to Azure Log Analytics
  • No file-based logs - Logs are streams, not files

Disposability

  • Fast startup - Services start in seconds, not minutes
  • Graceful shutdown - Handle shutdown signals, finish in-flight requests
  • Crash recovery - Kubernetes restarts failed containers automatically

Multi-Tenant Safe

  • Tenant isolation - Tenant context at every layer
  • No data leakage - Strict tenant filtering in queries
  • Tenant-aware scaling - Scale per tenant if needed

Observability Built-In

  • Logging, tracing, metrics - All three pillars from day one
  • Health checks - Built-in health check endpoints
  • Distributed tracing - OpenTelemetry integration

Stateless Services and Scalability

Stateless Design

Why: Stateless services scale horizontally without coordination.

How Templates Encourage Statelessness:

  • No in-memory state - All state in databases or caches
  • Session externalization - Sessions in Redis or database
  • Request-scoped dependencies - Dependencies created per request

Example:

// Stateless - no instance variables
public class InvoiceService
{
    private readonly IInvoiceRepository _repository; // Injected per request

    public async Task<Invoice> GetInvoiceAsync(Guid id)
    {
        return await _repository.GetByIdAsync(id); // State in database
    }
}

Horizontal Scaling

How It Works: - Kubernetes creates multiple pod replicas - Load balancer distributes requests across replicas - Each replica handles requests independently - No coordination needed between replicas

Scaling Triggers: - CPU utilization - Memory usage - Request rate - Custom metrics (e.g., queue length)

Configuration and Secrets

Configuration Management

External Config Service: - Use ConnectSoft Config Platform for runtime configuration - Feature flags, connection strings, business rules - Changes without redeployment

Environment Variables: - Deployment-time configuration (e.g., environment name, region) - Set in Kubernetes ConfigMaps - Different values per environment

Example:

# Kubernetes ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: invoice-service-config
data:
  Environment: production
  Region: eastus
  LogLevel: Information

Secrets Management

Azure Key Vault: - Store secrets (connection strings, API keys, certificates) - Access via managed identity - Automatic rotation support

User Secrets (Development): - Local development uses user secrets - Never commit secrets to source control - .gitignore includes secrets files

Example:

// Access Key Vault via managed identity
var secretClient = new SecretClient(
    new Uri("https://myvault.vault.azure.net/"),
    new DefaultAzureCredential());

var connectionString = await secretClient.GetSecretAsync("DatabaseConnectionString");

Tip

Always use Azure Key Vault for secrets in production. Never hardcode secrets or commit them to source control. Use managed identities for Key Vault access—no secrets needed to access secrets.

Resilience and Fault Tolerance

Retry Policies

Built-in Retries: - HTTP clients retry transient failures - Database connections retry on timeout - Event publishing retries on failure

Exponential Backoff: - First retry: immediate - Subsequent retries: exponential delay - Max retries: 3-5 attempts

Circuit Breakers

Purpose: Prevent cascading failures when downstream service is down.

How It Works: - Monitor failure rate - Open circuit after threshold failures - Fail fast while circuit is open - Close circuit after timeout

Library: ConnectSoft.Extensions.Http provides circuit breaker support

Timeouts

Request Timeouts: - All external calls have timeouts - Default: 30 seconds - Configurable per service

Connection Timeouts: - Database connections timeout after 15 seconds - HTTP connections timeout after 10 seconds

Health Checks

Built-in Health Checks: - /health endpoint for Kubernetes liveness probe - /health/ready endpoint for readiness probe - Checks database connectivity, external services

Example:

builder.Services.AddHealthChecks()
    .AddCheck<DatabaseHealthCheck>("database")
    .AddCheck<ExternalServiceHealthCheck>("external-service");

Tip

Use built-in resilience libraries (ConnectSoft.Extensions.Http, Polly) for retries, circuit breakers, and timeouts. Don't implement resilience logic yourself—use proven libraries.

Deployment Targets

Azure Container Apps

When to Use: - Serverless container workloads - Auto-scaling based on HTTP traffic - Simple deployment model

Characteristics: - Managed Kubernetes (simplified) - Pay per use - Built-in scaling

Azure Kubernetes Service (AKS)

When to Use: - Full Kubernetes control - Complex orchestration needs - Multi-region deployments

Characteristics: - Full Kubernetes API - Node pools and autoscaling - Advanced networking

Azure App Service (Legacy)

When to Use: - Simple web apps (legacy) - Not recommended for new services

Characteristics: - Platform-as-a-Service - Less control than containers - Easier deployment

Container-First Thinking

All Services Are Containerized: - Docker images for all services - Kubernetes manifests for deployment - Container registry (Azure Container Registry)

Benefits: - Consistent runtime environment - Easy local development (same as production) - Portable across environments - Version control for deployments

Example:

# Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "InvoiceService.Api.dll"]