Skip to main content

Architecture Overview

System Context

InventoryAlert is a real-time stock alerting and portfolio management system. The diagram below shows how it interacts with external systems and internal services.

Lean Vertical Slice Consolidation

To improve maintainability and reduce project-reference overhead, the solution uses a Lean Vertical Slice architecture since v2.

  • Consolidated Business Logic: There is no separate Application layer. Services live in InventoryAlert.Api and are grouped by feature slice (e.g., StockDataService, AlertRuleService, PortfolioService, WatchlistService).
  • Repository Strategy: Repositories are feature-specific rather than purely generic. StockListingRepository encapsulates EF Core queries, TradeRepository computes net holdings via SUM(Buy) - SUM(Sell).
  • Observability-first: All events flow through Seq (structured logging) with correlation IDs. No relational SystemEvent tables — keeps the DB clean.

Tech Stack

Backend

LayerTechnologyNotes
Runtime.NET 10 / C# 12Primary constructors, collection expressions
Web FrameworkASP.NET Core 10Minimal API + Controllers
ORMEF Core 10 + NpgsqlAsNoTracking() on all reads
Background JobsHangfire (PostgreSQL storage)Dashboard at /hangfire
Event BusAmazon SQSMocked locally with Moto
CacheRedis via StackExchange.Redis30s quote TTL, 30min dedup TTL
LoggingSerilog → SeqStructured logs, searchable at :5341
ValidationFluentValidationApplied at Web layer; Application layer trusts validated inputs

Frontend

LayerTechnologyNotes
FrameworkNext.js 15 (App Router + RSC)Server + Client component split
LanguageTypeScriptStrict mode
StylingTailwind CSS v4Finance-themed design system
Server StateReact QueryAuto-refresh, stale-while-revalidate, optimistic updates
UI StateZustandModal, filter, and selection state
ChartsRechartsPriceLineChart, EarningsBarChart, RecommendationDonut

Infrastructure

ComponentToolNotes
Relational DBPostgreSQL 17Via Docker, exposed on 5433
NoSQLAmazon DynamoDBMoto for local emulation on 5000
ObservabilitySeq (structured logs)http://localhost:5341
ContainerizationDocker + Docker ComposeAll services via single compose up
NotificationsIn-App Notification tableReplaces legacy Telegram integration
CacheRedis 7Dedup + quote + alert cooldown

Docker Services & Cloud Topology

Local Development Containers (docker-compose.yml)

ContainerImagePortRole
inventory-apiCustom .NET 108080REST API Host
inventory-workerCustom .NET 108081Background jobs
inventory-dbpostgres:17-alpine5433PostgreSQL
inventory-cacheredis:7.2-alpine6379Redis
inventory-seqdatalust/seq5341Structured log viewer
inventory-motomotoserver/moto5000DynamoDB + SQS emulator
inventory-uiCustom Next.js3000Frontend

☁️ Production Cloud Deployment ($0/Month Topology)

  • Backend Web Service (Render): Single container running API (Port 8080), Worker (Port 8081), and Moto emulator (Port 5000).
    • Live Endpoint: https://inventorymanagementsystem-s55e.onrender.com
    • /aws Proxy Route: Reverse-proxies traffic to Moto on port 5000 for remote dynamodb-admin and AWS CLI management.
  • Relational DB (Neon.tech): PostgreSQL Managed Instance (IPv4 pooled connection string).
  • Cache (Upstash): Managed Redis with TLS.
  • Frontend UI (Vercel): Next.js 15 App Router deployed to global CDN.
  • Uptime Keep-Alive: KeepAliveJob self-pings http://127.0.0.1:8080/healthz every 10 minutes to prevent Render free-tier sleep.