Software Architecture Guide
Introductionβ
Welcome to the Software Architecture Guide! This document is designed to provide you with clear and actionable guidance to help you design and implement robust, scalable, and maintainable applications using Microsoft technologies.
By adhering to these guidelines, we can build software that is not only functional but also resilient and easy to evolve. If you have suggestions for improving this guide, please let us know!
Guiding Principlesβ
π§© Simplicity: Keep the architecture simple and avoid over-engineering. Solve todayβs problems while considering tomorrowβs needs.
π Scalability: Design for growth. Ensure the application can handle increased load without significant rework.
π οΈ Maintainability: Write code thatβs easy to read, test, and update. Favor clear, modular, and well-documented designs.
βοΈ Cloud-Native: Leverage Azureβs PaaS offerings effectively to optimize costs and reliability.
π Security by Design: Incorporate security practices into every stage of development.
π Observability: Build for easy monitoring and diagnostics, enabling quick issue detection and resolution.
π Adaptability: Design systems to accommodate future changes, such as evolving business requirements or technology updates.
π Standardization: Use consistent libraries, frameworks, and coding practices across all projects to reduce complexity and streamline onboarding for new developers.
Core Components of Our Applicationsβ
Frontendβ
Framework Choiceβ
- Use Blazor for building interactive and modern web interfaces. It provides a seamless developer experience with full-stack .NET.
Why Blazor?β
-
Offers component-based architecture, promoting reuse and maintainability.
-
Eliminates the need for JavaScript in many cases, streamlining development.
-
Provides a consistent technology stack, reducing context-switching for developers familiar with .NET.
Best Practicesβ
-
Organize UI components by feature within the Features folder structure (e.g.,
Features/Orders/Components
). -
Follow a clean separation of concerns by avoiding business logic in UI components.
-
Use CSS isolation for component styles to prevent conflicts.
Use .NET 9 if:
-
You want to leverage the latest features, APIs, and performance improvements.
-
Your project is new or can easily adapt to the latest version.
-
You prioritize staying on the cutting edge of development tools.
Use .NET 8 if:
- Your project requires long-term support (LTS).
- Stability and extended maintenance are critical for your application's lifecycle.
Recommendation
-
For production environments that require stability and support, .NET 8 (LTS) is typically the better choice.
-
If you're working on experimental or new projects and want the latest advancements, go with .NET 9.
-
Always review the official Microsoft .NET Support Policy to align your choice with your support requirements.
Backendβ
Framework Choiceβ
- Use ASP.NET Core for building scalable and high-performance web APIs.
Why ASP.NET Core?β
-
Provides excellent performance and a lightweight runtime.
-
Supports a modular architecture with middleware, making it easy to customize request handling.
-
Seamless integration with Azure services.
API-First Approachβ
-
Define and document APIs first using Swagger/OpenAPI to ensure clear contracts between frontend and backend.
-
Design APIs to be versioned and backward-compatible to support evolving requirements.
Project Structureβ
-
Organize code by feature (e.g.,
Features/Orders
,Features/Users
) to improve modularity and scalability. -
Within each feature folder, use subfolders for Controllers, Services, and Models.
-
Apply Service Layer Abstraction to encapsulate business logic and promote reusability.
Azure Cloudβ
Our journey to Azure reflects our evolving needs:
On-Premise to IaaS
- We initially transitioned from on-premise infrastructure to Infrastructure as a Service (IaaS) to reduce hardware management overhead and improve scalability.
IaaS to PaaS
- Moving to Platform as a Service (PaaS) allowed us to focus on application development rather than infrastructure management. PaaS provides out-of-the-box scalability, security, and integration with Azure services.
Future Considerations: Transition to Containers
While PaaS is our current focus, we anticipate transitioning to containerized deployments in the future for enhanced control and flexibility. This transition may include:
-
Azure Kubernetes Service (AKS): For orchestrating containerized applications with fine-grained scalability and advanced deployment options.
-
Azure Container Apps (ACA): For simpler containerized workloads that donβt require full Kubernetes capabilities.
Use PaaS Offeringsβ
-
Use App Service for hosting web and API applications.
-
Leverage Azure SQL Database for relational data storage.
-
Implement Azure Blob Storage for unstructured data.
-
Use Azure Application Insights for monitoring and observability.
-
Utilize Azure Functions for lightweight, event-driven computing needs.
-
Use Azure Service Bus or Event Grid for messaging and event-driven architecture.
Best Practicesβ
Please refer to the Azure Naming Convention Guide for guidelines on naming Azure resources.
Application Hostingβ
-
Deploy APIs and Blazor applications to Azure App Service with proper configuration for staging and production environments.
-
Enable auto-scaling based on CPU and memory usage.
Securityβ
-
Use Managed Identity for secure access to Azure resources, avoiding hardcoded credentials.
-
Store secrets, connection strings, and API keys in Azure Key Vault.
-
Apply network restrictions using Virtual Network Integration or IP restrictions.
Data Storageβ
-
Design Azure SQL Database schemas with scalability in mind. Use partitioning where needed.
-
Use Blob Storage lifecycle policies to manage costs by archiving or deleting unused data.
Monitoring and Observabilityβ
-
Configure Application Insights to collect detailed telemetry for performance tracking and troubleshooting.
-
Set up custom alerts to proactively monitor performance bottlenecks and failures.
Cost Optimizationβ
-
Leverage Azure Advisor to identify cost-saving opportunities.
-
Use Azure's Reserved Instances and Spot VMs where appropriate.
Backup and Recoveryβ
-
Enable automatic backups for Azure SQL Databases with proper retention policies.
-
Use Azure Recovery Services for disaster recovery plans.
Blue-Green Deploymentsβ
- Minimize downtime by deploying to a staging slot and swapping to production after validation.
Infrastructure as Code (IaC)β
- Use Bicep to define infrastructure.
The Azure Well-Architected Framework is a guide to building secure, reliable, efficient, and cost-effective cloud solutions.
Read about it here: https://learn.microsoft.com/en-us/azure/well-architected/what-is-well-architected-framework
Authentication and Authorizationβ
- Use Microsoft Entra B2B for managing user authentication, unless there is a specific requirement that prevents its use. In such cases, consider Azure AD B2C instead.
When to Use Azure AD B2C vs. Microsoft Entra B2B
Azure AD B2C:
-
Use when building applications that require authentication for external customers or consumers.
-
Ideal for scenarios where you need customizable user experiences, such as branded login pages and multi-factor authentication.
-
Supports social identity providers (e.g., Google, Facebook) and local accounts with username/password.
Microsoft Entra B2B:
-
Use when enabling collaboration with external partners, vendors, or organizations.
-
Allows external users to securely access your internal resources using their own existing Azure AD or other identity systems.
-
Ideal for scenarios like sharing documents or applications within a secure enterprise context.
- Follow Role-Based Access Control (RBAC) principles for permissions.