GMI · TECHNOLOGY OBSERVATORY // ALL SYSTEMS NOMINAL
ENGINEERED BY LEOPARD DATA

System Patterns

Design patterns and architectural principles implemented throughout the Grade My Investments platform.

ASYNC REQUEST-REPLY PATTERN
rendering diagram…
sequenceDiagram
    participant U as User
    participant AF as Azure Functions
    participant DB as MySQL
    participant RE as Report Engine
    participant FMP as FMP API
    participant BS as Blob Storage
    participant NS as Notification

    U->>AF: POST generate report
    AF->>DB: create Job row
    AF-->>U: 202 Accepted
    RE->>DB: poll for pending jobs
    DB-->>RE: job ready
    RE->>FMP: fetch financial data
    FMP-->>RE: stock data
    RE->>BS: upload Excel report
    RE->>DB: update job status
    DB->>NS: trigger email - SMS
    NS-->>U: job complete notification
    U->>AF: GET job folder
    AF-->>U: SAS download URL
Report generation as the canonical async request-reply pattern: submit, process, notify, poll, retrieve.

Core Architectural Patterns

Layered Architecture

Clean separation between presentation, business, and data layers

  • Presentation (Blazor WASM, MAUI)
  • Services (Business Logic)
  • Data Access (Repository)
  • Database (MySQL)
Microservices Architecture

15 independent console applications for different business concerns

  • Report Engine & Report Generator Alpha
  • Claude Analysis & Report Comparison
  • Email Sender & SMS Sender
  • Billing Engine & Schedules Engine
  • Download Builder & File Purge
  • Health Monitor

Foundational Design Patterns

Dependency Injection

Implementation: Throughout entire system

Locations:
  • Azure Functions Program.cs: Lines 22-94
  • Client Web Program.cs: Lines 48-102
  • Admin Web Program.cs: Lines 47-134
  • Report Generator Program.cs: Lines 177-227

Benefits: Loose coupling, testability, maintainability

Repository Pattern

Implementation: Data access abstraction layer

Locations:
  • RepositoriesInterfaces.cs: 45 interfaces
  • Repositories.cs: Concrete implementations
  • Entity Framework integration

Benefits: Data access abstraction, unit testing support

Rate Limiting (Token Bucket)

Implementation: Custom token bucket algorithm

Location:
  • ReportGeneratorAlpha/RateLimiter.cs
  • 3,000 calls per minute limit
  • Semaphore-based concurrency control

Benefits: API quota protection, system stability

RESTful API Pattern

Implementation: Azure Functions HTTP triggers

Location:
  • AzureFunctions/Functions.cs
  • Standard HTTP verbs (GET, POST, PUT, DELETE)
  • Route patterns with parameters

Benefits: Standardized API interface, scalability

Factory Pattern

Implementation: HTTP Client Factory

Locations:
  • Client Web: IHttpClientFactory
  • Admin Web: AddHttpClient()
  • MAUI: Named HTTP clients

Benefits: Resource management, configuration reuse

Builder Pattern

Implementation: Configuration and setup

Locations:
  • MAUI: MauiApp.CreateBuilder()
  • Blazor WASM: WebAssemblyHostBuilder
  • Service configuration chains

Benefits: Fluent configuration, step-by-step construction

Paging Pattern

Implementation: Server-side pagination with skip/take

Locations:
  • Client Web: Portfolio, Trade History, Reports
  • Admin Web: User management, System logs
  • Repository pattern: Skip().Take() methods
  • Blazor components: Paginated data display

Benefits: Performance optimization, improved user experience, memory efficiency

FIFO Queue Pattern

Implementation: First-In-First-Out message processing queues

Locations:
  • EmailSender Console App: Queue-based email processing
  • SMS Sender Service: Sequential message delivery
  • Report Engine Alpha: Report generation queue management
  • MySQL Database tables used for queueing mechanism

Benefits: Message ordering guarantee, system reliability, load distribution, fault tolerance

ML.NET Pipeline Pattern

Implementation: Machine learning model training and prediction pipelines

Locations:
  • PyEasy Console: MLForecastingService.cs
  • Report Generator Alpha: MLForecastingService.cs
  • SSA forecasting with fallback to linear regression
  • Multiclass classification for sentiment analysis

Benefits: Predictive analytics, data-driven insights, confidence intervals, anomaly detection

Enterprise Patterns

Unit of Work

Implementation: Entity Framework DbContext

  • GmiDbContext manages transactions
  • SaveChangesAsync() commits as single unit
  • 61 DbSets for entity management
Service Layer

Implementation: Business logic orchestration

  • ServicesInterfaces.cs: 50+ interfaces
  • Services.cs: Concrete implementations
  • Repository orchestration with validation
Options Pattern

Implementation: Configuration management

  • IConfiguration throughout system
  • appsettings.json configuration
  • Environment-specific settings
Strategy Pattern

Implementation: Authentication strategies

  • Google OAuth for Client Web
  • Azure AD for Admin Web
  • JWT Bearer for API authentication
Command Pattern

Implementation: Azure Functions

  • Each Function = Command
  • Encapsulated request processing
  • Standardized error handling
Adapter Pattern

Implementation: External API integration

  • FmpApiClient for Financial Modeling Prep
  • BlobStorageService for Azure Storage
  • REST client services for HTTP APIs

CQRS Pattern (Command Query Responsibility Segregation)

Grade My Investments applies the CQRS pattern in the Admin Web application where read operations (queries) and write operations (commands) are handled through distinct service methods with purpose-built interfaces. This separation enables optimized query paths for search/filtering while keeping mutation logic clean and auditable.

Query Side (Read-Optimized)
Activity Log Search

Interface: IActivityLogEntryService

  • GetByAccountIdAsync(accountId, limit) - filtered by account
  • GetByAccountIdAndTypeAsync(accountId, type, limit) - filtered by type (PageView, LinkClick, Operation)
  • Indexed on AccountID, ActivityDateTime, and ActivityType
Email Queue Search

Interface: IMessagingService

  • GetEmailsWithFilterAsync(status, fromDate, toDate, searchText, pageSize, pageNumber)
  • Supports pagination, date range filtering, status filtering, and text search
  • Used by Admin Web to browse sent, pending, and failed emails
SMS Queue Search

Interface: IMessagingService

  • GetSmsWithFilterAsync(status, fromDate, toDate, searchText, pageSize, pageNumber)
  • Same filtering capabilities as email search
  • Used by Admin Web to monitor SMS delivery and troubleshoot failures
Command Side (Write-Optimized)
Activity Logging Commands

Interface: IActivityLogEntryService

  • LogPageViewAsync(accountId, pageName)
  • LogLinkClickAsync(accountId, linkName, url)
  • LogOperationAsync(accountId, operationName, detail)
  • All fire-and-forget - never blocks user operations
Email/SMS Enqueue Commands

Interface: IMessagingService

  • EnqueueEmailToSendAsync(to, cc, bcc, subject, body)
  • EnqueueSmsToSendAsync(subject, body, toNumber)
  • MarkEmailAsSentAsync(id) / MarkSmsAsSentAsync(id)
  • RecordEmailSendFailureAsync(id, error) / RecordSmsSendFailureAsync(id, error)
Why CQRS Here?
  • Writes are high-volume, fire-and-forget (every click/page view)
  • Reads need complex filtering, pagination, and date ranges
  • Admin Web queries never interfere with client write paths
  • Database indexes optimized separately for read vs write patterns

Microsoft Cloud Design Patterns

Grade My Investments implements numerous patterns from the Microsoft Azure Cloud Design Patterns catalog. These proven patterns address common challenges in distributed cloud applications including reliability, scalability, and security.

Queue-Based Load Leveling

Implementation: Database-backed queues with background consumers

  • emailstosend table queues outbound emails for the EmailSender service
  • smstosend table queues outbound SMS for the SmsSender service
  • downloads table queues ZIP build requests for the DownloadBuilder service
  • Decouples user-facing API from slow external calls (SendGrid, Twilio, blob storage)
Competing Consumers

Implementation: Horizontally scalable background services

  • EmailSender, SmsSender, and DownloadBuilder are stateless consumers
  • Multiple instances can run concurrently, each claiming pending items
  • ReportEngine supports ProcessorCount * threadsPerCore concurrent reports
  • Configurable batch sizes allow tuning throughput per instance
Retry Pattern

Implementation: Configurable retry with failure tracking and exponential backoff

  • Email and SMS senders retry up to 3 times before marking as permanently failed
  • RetryCount field on EmailToSend and SmsToSend tracks attempts
  • RecordEmailSendFailureAsync() increments retry count and preserves error details
  • MarkEmailAsFailedAsync() terminates retries after max attempts
  • FMP API calls use exponential backoff (1s, 2s, 4s) on 429 rate limits and 5xx server errors
  • FMP proxy and client both implement retry — resilient at every layer
  • Stripe payment recording retries with FailedPaymentReconciliation fallback
Bulkhead Pattern

Implementation: Rate limiting and resource isolation

  • RateLimitingMiddleware enforces per-account/per-IP token bucket limits
  • Authenticated users: 100 requests/minute; anonymous: 30 requests/minute
  • FMP API rate limiter isolates external API call budget from user requests
  • Prevents any single user from exhausting system resources
Health Endpoint Monitoring

Implementation: Dedicated health monitor service + API health endpoints

  • HealthMonitor systemd service runs every 60 seconds, collecting disk/memory/CPU, database connectivity, external API reachability (FMP, Anthropic, SendGrid, Blob Storage)
  • Monitors all 11 background service statuses via systemctl is-active
  • Tracks queue depths, stale jobs, log file sizes, and system uptime
  • Persists health checks to systemhealthchecks table with Warning/Critical/Healthy status
  • Admin Web dashboard displays real-time health banner with warning details
  • Dedicated System Health page with auto-refresh, history, and color-coded metrics
Valet Key Pattern

Implementation: SAS tokens for Azure Blob Storage

  • GenerateSasUrl() creates time-limited, read-only SAS tokens
  • Download ZIP files served via SAS URLs (1-hour expiry)
  • Clients access blob storage directly without proxying through the API
  • Reduces API server load and bandwidth for large file downloads
Gateway Aggregation

Implementation: Azure Functions as unified API gateway

  • Single API endpoint aggregates all backend services
  • Middleware pipeline: Authentication, Rate Limiting, Security Headers, CORS
  • FMP proxy endpoint hides third-party API key from clients
  • Allowlisted FMP paths prevent abuse of proxied external API
Backends for Frontends (BFF)

Implementation: RestClient service layer per frontend

  • Gmi.RestClient provides typed service interfaces for all frontends
  • Client Web, Admin Web, and Mobile each register the same services via DI
  • Abstracts HTTP communication, token management, and error handling
  • AddGmiRestClient() extension method configures per-app service sets
Saga Pattern

Implementation: Multi-step transactions with compensating rollback

  • CreateReportJobWithDataAsync() orchestrates: job creation, symbol list association, notification settings, coupon application
  • Wrapped in Database.BeginTransactionAsync() with rollback on any step failure
  • Credit card default-swap uses transaction to prevent race conditions
  • Admin notifications fire after commit (fire-and-forget, no rollback needed)
Sidecar Pattern

Implementation: 11 independent background services as systemd units

  • ReportEngine — orchestrates multi-threaded report generation jobs (spawns ReportGeneratorAlpha child processes)
  • ClaudeAnalysis — AI-powered report analysis via Anthropic API
  • ReportComparison — period-over-period report comparison
  • EmailSender — processes email queue via SendGrid
  • SmsSender — processes SMS queue via Twilio
  • BillingEngine — handles recurring billing cycles
  • SchedulesEngine — executes scheduled report generation
  • DownloadBuilder — builds ZIP archives from folders
  • FilePurge — cleans up soft-deleted files from blob storage
  • HealthMonitor — system health monitoring and alerting
Cache-Aside Pattern

Implementation: In-memory response and token caches with explicit TTL

  • FmpProxyFunctions caches upstream FMP responses for 5 minutes, emitting X-Cache: HIT/MISS headers
  • GoogleTokenValidator and EntraIdTokenValidator cache validated tokens to avoid re-hitting Google and Microsoft identity endpoints on every request
  • Stale entry sweep triggers when cache size exceeds 1,000 entries
  • Shields upstream APIs from duplicate load while preserving correctness via short TTLs
Claim Check Pattern

Implementation: Metadata in MySQL, large payloads in Azure Blob Storage

  • File entity stores BlobContainer + BlobPath references; binary content lives in Azure Blob Storage
  • Download entity stores blob path for generated ZIP archives; SAS URL returned on retrieval
  • Keeps DB rows small and scan-friendly while letting clients stream large artifacts directly from blob
  • MAUI uploads stream to blob first, then the claim (AccountEmailAddressID / FileID) is persisted in MySQL
Asynchronous Request-Reply

Implementation: Client submits, polls status, retrieves result

  • Downloads: client creates a downloads row, DownloadBuilder builds the ZIP asynchronously, client polls until Status = Ready, then fetches the SAS URL
  • Report generation: client creates a Job, ReportEngine processes it, email/SMS notifications fire on completion
  • Claude analysis: ClaudeAnalysisJob created, ClaudeAnalysis service processes via Anthropic API, client polls for results
  • Avoids long-lived HTTP connections and frees the Functions host from blocking on multi-minute work
Publisher-Subscriber (Pub/Sub)

Implementation: Stripe webhooks as durable event subscription

  • Stripe publishes charge.succeeded, payment_method.attached, invoice.payment_failed, etc.
  • StripeWebhookFunctions subscribes via HTTPS endpoint with signature verification
  • StripeWebhookEvent table records every received event for idempotent processing — duplicates are detected and skipped
  • Decouples payment outcome from user-facing request path; replay-safe for Stripe's at-least-once delivery
External Configuration Store

Implementation: Azure Key Vault with managed-identity access

  • Connection strings, Stripe / SendGrid / Twilio / FMP API keys all stored as Key Vault secrets
  • App Services resolve secrets at runtime via @Microsoft.KeyVault(VaultName=...;SecretName=...) references — no secrets in source or app settings
  • System-assigned managed identities on each workload grant least-privilege get/list access
  • Secret rotation is a Key Vault operation — no redeploy required
Federated Identity

Implementation: Dual identity providers with a unified account model

  • Client Web & MAUI authenticate through Google OAuth; tokens validated by GoogleTokenValidator
  • Admin Web authenticates through Microsoft Entra ID; tokens cryptographically validated by EntraIdTokenValidator (issuer, tenant, appid, signature)
  • Both flows resolve to a local Account or AdminUser record, letting the rest of the system stay identity-provider-agnostic
  • No password storage — authentication is delegated to the identity provider
Static Content Hosting

Implementation: Blazor WebAssembly deployed as static files

  • Client Web, Admin Web, and Technology Web are Blazor WASM single-page apps — compiled to .wasm/.dll/.js assets
  • Served from Azure App Service (Windows) with WEBSITE_RUN_FROM_PACKAGE=1 — no server-side rendering per request
  • All dynamic data comes from the Azure Functions API; the web tier is pure static delivery
  • Trivial to scale out — every instance serves the identical read-only asset set
Ambassador Pattern

Implementation: FMP proxy as outbound egress ambassador

  • FmpProxyFunctions is the only path through which clients reach the Financial Modeling Prep API
  • Injects the FMP API key server-side, preventing key leakage to browsers/mobile clients
  • Enforces an allowlist of FMP paths so the proxy can't be abused to call arbitrary endpoints
  • Adds caching, logging, and rate-limiting on behalf of every caller — one place to add cross-cutting policies for the upstream service
Scheduler Agent Supervisor

Implementation: SchedulesEngine schedules, ReportEngine executes, HealthMonitor supervises

  • Scheduler: SchedulesEngine evaluates ReportGenerationSchedule cron expressions and creates pending Job rows at the right time
  • Agents: ReportEngine, ReportGeneratorAlpha, ClaudeAnalysis, DownloadBuilder pick up pending work and perform long-running operations
  • Supervisor: HealthMonitor checks stale-job counters, queue depths, and systemctl is-active for each agent, raising SystemHealthCheck entries on anomalies
  • Missed schedules and crashed agents surface in the Admin dashboard health banner
Deployment Stamps

Implementation: Dev and Prod as fully isolated Pulumi stacks

  • Gmi.Pulumi.Infrastructure.Dev and Gmi.Pulumi.Infrastructure.Prod each provision a complete stamp: RG, VNet, subnets, MySQL Flexible Server, Blob Storage, Key Vault, App Service Plan(s), Function App, 3 Web Apps, Report VM, NSGs
  • No shared infrastructure between stamps — dev changes can never affect prod traffic
  • Resource naming convention (gmiapp-{env}-*) makes the stamp boundary explicit across every resource
  • Same code path deploys to each stamp — scales to additional stamps (regional, tenant-specific) without refactoring

12-Factor App Methodology

Grade My Investments adheres to the 12-Factor App methodology, a set of best practices for building modern, cloud-native software-as-a-service applications. Originally published by Heroku engineers, these factors ensure applications are portable, scalable, and maintainable in cloud environments.

ICodebase

One codebase tracked in revision control, many deploys

  • Single Azure DevOps Git repository
  • Trunk-based development with master and develop branches
  • Same codebase deploys to dev and production environments
IIDependencies

Explicitly declare and isolate dependencies

  • All NuGet packages declared via PackageReference in .csproj files
  • No system-wide package dependencies assumed
  • dotnet restore resolves all dependencies from package feed
IIIConfig

Store config in the environment

  • Azure Key Vault for secrets (connection strings, API keys)
  • Environment variables override appsettings.json
  • Pipeline variable groups inject environment-specific config at deploy time
IVBacking Services

Treat backing services as attached resources

  • MySQL via connection string (swappable between local and Azure)
  • Azure Blob Storage via connection string
  • Stripe, SendGrid, Twilio, FMP API all configured via injected settings
VBuild, Release, Run

Strictly separate build and run stages

  • Build: Azure Pipelines compiles all projects, runs 695 unit and integration tests
  • Release: Publishes artifacts with environment-specific config
  • Run: Deploys to Azure App Services, VMs, and Azure Functions
VIProcesses

Execute the app as one or more stateless processes

  • Azure Functions are stateless HTTP handlers
  • Console workers are stateless queue consumers
  • All state persisted to MySQL or Azure Blob Storage
VIIPort Binding

Export services via port binding

  • Blazor apps self-host via ASP.NET Core Kestrel
  • Azure Functions expose HTTP endpoints via runtime
  • No external web server dependency (no IIS required)
VIIIConcurrency

Scale out via the process model

  • 11 independent background services scalable as separate processes
  • Azure Functions auto-scale on demand
  • ReportEngine uses ProcessorCount * threadsPerCore concurrency
IXDisposability

Maximize robustness with fast startup and graceful shutdown

  • CancellationToken propagated through all console apps
  • Ctrl+C / SIGTERM handled for graceful shutdown
  • Scoped DI services ensure proper resource cleanup via IDisposable
XDev/Prod Parity

Keep development, staging, and production as similar as possible

  • Pulumi IaC provisions identical resource types in dev and prod
  • appsettings.Development.json overrides only connection strings
  • Same Docker-compatible .NET runtime in both environments
XILogs

Treat logs as event streams

  • ILogger<T> injected across all services (450+ usages)
  • Structured logging with named placeholders ({AccountId}, {JobId})
  • Serilog integration available for advanced sinks
XIIAdmin Processes

Run admin/management tasks as one-off processes

  • BillingEngine CLI: billing-report, charge, charge-account
  • Console apps support run-once mode for single execution
  • SQL migration scripts in migrations/ folder for schema changes

Domain-Driven Design (DDD)

Grade My Investments' architecture is organized around Domain-Driven Design principles as described by Eric Evans. The system is decomposed into distinct bounded contexts, each with its own entities, services, and repositories. A ubiquitous language drawn from the financial services and report generation domain ensures that code reads like business requirements.

Bounded Contexts

Account Management
IAccountService, IAccountEmailService, IAccountSmsService
Account, AccountEmailAddress, AccountSmsNumber
Billing
IBillingService, IChargeService, IInvoiceService, IPaymentService
Invoice, Charge, Payment, BillingRun, ServicePricing
Report Generation
IJobService, IReportGenerationScheduleService, ISymbolListService
Job, JobSymbolList, JobCharge, SymbolList, ReportGenerationSchedule
File Storage
IFileService, IFolderService, IBlobStorageService, IDownloadService
Folder, File, Download, FileDownload
Notifications
IMessagingService, IAdminNotificationEmailService, IJobNotificationService
EmailToSend, SmsToSend, AdminNotificationEmailAddress
Payment Processing
IStripePaymentService, ICreditCardService, ICouponCodeService
CreditCard, StripeWebhookEvent, CouponCode, CouponUsage
AI Analysis
IClaudeAnalysisService, IReportComparisonService
ClaudeAnalysisJob, ClaudeAnalysisRequest, ReportComparisonJob
Portfolio
IPositionReportService, ISymbolListTemplateService
PositionReport, PositionReportListItem, SymbolListTemplate
System Monitoring
ISystemHealthCheckService, IDashboardService, ICriticalErrorLogService
SystemHealthCheck, CriticalErrorLog, ActivityLogEntry, AuditLog

DDD Building Blocks

Entities

Objects with unique identity persisted across the system lifecycle.

  • 50 domain entities in Gmi.ClassLibrary/Models.cs
  • Each has a [Key] identity field (e.g., AccountID, JobID)
  • Examples: Account, Job, Invoice, Folder, CreditCard
Aggregates

Clusters of entities treated as a unit for data changes, accessed through an aggregate root.

  • Account Aggregate: Account (root) + EmailAddresses, SmsNumbers, CreditCards, AccountFolders
  • Job Aggregate: Job (root) + JobSymbolLists, JobCharges, JobNotificationSettings
  • Billing Aggregate: Invoice (root) + InvoiceCharges, Charges
  • Folder Aggregate: Folder (root) + Files, ChildFolders, Downloads
Value Objects

Immutable objects defined by their attributes, not identity.

  • AccountEmailValidationToken — temporary, identity-less
  • ServicePricing — immutable business rules for pricing
  • StorageProperties — computed folder/file metadata
Domain Services

Operations that don't belong to a single entity, encapsulating cross-entity business logic.

  • BillingService.ProcessMonthlyBillingAsync() — orchestrates charges, payments, invoices
  • JobService.CreateReportJobWithDataAsync() — coordinates job + symbol lists + notifications + coupons
  • PaymentService.ProcessStripePaymentAsync() — payment with reconciliation
Domain Events

Notifications that something meaningful happened in the domain.

  • Account created → SendNewAccountNotificationAsync()
  • Report generated → SendReportGeneratedNotificationAsync()
  • Payment failed → FailedPaymentReconciliation entity persisted
  • Stripe webhook → StripeWebhookEvent captured as external event
Ubiquitous Language

Code uses the same terminology as the business domain.

  • Billing: Invoice, Charge, Payment, BillingRun, ServicePricing
  • Jobs: Job, JobStatus, SymbolList, PositionReport, ReportGenerationSchedule
  • Storage: Folder, File, Download, FileDownload
  • Methods: ProcessMonthlyBillingAsync, ApplyCouponCodeToJobAsync, RequestFolderDownloadAsync

Repository per Aggregate

Grade My Investments implements 46 repository interfaces in RepositoriesInterfaces.cs, each aligned to an aggregate boundary. Repositories encapsulate data access for their aggregate root and its children, ensuring that all persistence operations go through a well-defined contract.

Modern Development Patterns

Async/Await Pattern

Throughout entire codebase for non-blocking operations

  • • All service methods return Task<T>
  • • Database operations with async
  • • HTTP calls with cancellation tokens
  • • File operations with async I/O
Extension Methods

Fluent API extensions for configuration

  • • ServiceCollectionExtensions.cs
  • • AddGmiRestClient()
  • • Complex service registration logic
  • • Fluent configuration patterns
Observer Pattern

Event handling in MAUI mobile applications

  • • XAML event binding
  • • Button click handlers
  • • Navigation events
  • • Page lifecycle events

SEO Page Generation Patterns

The free public ticker grade pages (/grade/{TICKER}) introduced a family of patterns for generating thousands of crawlable static pages from live data on read-only cloud hosting — several born directly from production incidents during the feature's first day.

  • Static Site Generation (Prerender Pipeline): Razor components render to plain HTML at build/generation time; a hybrid rewrite layer serves static pages and the WASM app from one URL space.
  • Last-Known-Good Snapshot Fallback: every ticker caches its generated grade, stats, and summary — an upstream FMP failure serves the previous snapshot instead of breaking the page or the run.
  • Change-Detection Gating: Claude summaries regenerate only when a ticker's grade actually changes — cost-aware AI invocation keyed on business state, not schedules.
  • Artifact Composition on Read-Only Hosting: generation runs where the data lives (report VM), output lands in blob storage, and the deploy pipeline composes it into the immutable run-from-package site.
  • Deterministic Rendering: unchanged data produces byte-identical output — stable ordering, no timestamps in markup — so re-runs and diffs stay meaningful.
  • Orphaned-Job Reclamation: the single-runner job queue requeues anything stuck in Running at service startup, surviving deploys and crashes mid-run.
  • Chunked Checkpointing with Live Progress: the ~2,500-ticker batch saves in chunks of 50 with live counters, so operators see progress mid-run and interruptions lose minutes, not hours.
  • Progressive Enhancement + Viewport-Lazy Assets: pages are fully functional with JavaScript disabled; search, group filters, signed-in detection, and the 1MB Mermaid engine (scroll-into-view) layer on top.

Application-Level Patterns

Beyond foundational and cloud design patterns, Grade My Investments implements several application-level patterns that solve recurring cross-cutting concerns across the platform.

Real-time Notification Bar

Implementation: Admin notification bar component that polls /admin/queue-counts every 60 seconds

  • Shows system health status with color-coded indicators (critical=red, warning=yellow)
  • Displays action queue counts for support requests, feature requests, bug reports, and feedback
  • Persistent top bar in admin layout provides at-a-glance operational awareness
Announcement & Maintenance Banners

Implementation: Shared Blazor components injected into layouts

  • AnnouncementBanner and MaintenanceBanner poll for active items on page load
  • Announcements support severity levels and date-range visibility windows
  • Maintenance windows display scheduled downtime with countdown details
  • Dismissible banners with session-scoped persistence
Collapsible Navigation Groups

Implementation: Expandable/collapsible sidebar navigation sections

  • Both admin and client nav menus use grouped navigation with CSS transitions
  • Groups collapse/expand on click with smooth animation
  • Active group auto-expands based on current route
  • Reduces visual clutter as the page count grows
Database-Backed Content Management

Implementation: CRUD pattern for all content entities

  • Blog, Knowledge Base, Changelog, and Announcements all stored in MySQL
  • Admin CRUD pages for each content type with publish/draft workflow
  • Slug-based URL routing for SEO-friendly public pages
  • View count tracking for blog posts
Multi-Channel Customer Feedback Pipeline

Implementation: 4 feedback channels following a consistent pattern

  • Support requests, feature requests, bug reports, and platform feedback
  • All follow: submit → admin notification email → admin review → user notification
  • Each has dedicated admin management pages with status workflows
  • Consistent REST API pattern across all 4 channels
Email Preference Upsert

Implementation: CreateOrUpdate pattern for per-account email preferences

  • Unique constraint on AccountID ensures one preference record per account
  • PUT endpoint creates if not exists, updates if exists (upsert)
  • Granular opt-in/opt-out toggles for each notification category
Account Data Export

Implementation: GDPR-style data export via aggregated JSON download

  • Single API endpoint aggregates data from multiple tables (account, jobs, files, billing, activity)
  • JSON response downloaded via JavaScript interop blob conversion
  • Supports data portability and privacy compliance requirements
URL Redirect Pattern

Implementation: Multi-route Blazor page for backward-compatible URLs

  • BlogRedirects page catches old static blog URLs and redirects to new slug-based routes
  • Multiple @page directives on a single component map old paths to new destinations
  • Preserves SEO value and prevents broken bookmarks during URL migration
Pattern Summary
45+ Design Patterns
21 Cloud Patterns
46 Repository Interfaces
61 Entity DbSets
50+ Service Interfaces
Pattern Benefits
  • Maintainability: Clean separation of concerns
  • Testability: Dependency injection enables mocking
  • Scalability: Microservices and async patterns
  • Reusability: Interface-based design
  • Flexibility: Strategy and factory patterns
  • Predictive Intelligence: ML.NET integration for forecasting
Implementation Quality
SOLID Principles 95%
Clean Architecture 90%
Design Patterns 88%
Code Consistency 92%
Best Practices
  • Consistent dependency injection across all layers
  • Interface segregation for testability
  • Async/await for all I/O operations
  • Configuration pattern for all settings
  • Repository pattern for data access abstraction