Architecture

Operyn is built as a Bun + Turborepo monorepo with a modular-monolith backend centered on core-platform, plus a separate ingestion edge service. It follows clean architecture principles: domain logic is framework-free, infrastructure adapters are injected, and asynchronous work is coordinated through BullMQ.

Service Map

ServicePortResponsibility
ingestion3001Accepts log/metric payloads, validates, indexes, and enqueues them
core-platform3003Incidents, remediation, notifications, AI diagnosis, team/integration workflows
dashboard3000Next.js 15 operations console with real-time incident management
docs3006Documentation site (Next.js)

Data Flow

External Systems (CloudWatch, Prometheus, App Logs)
      │
      ▼
┌─────────────────┐
│   Ingestion     │  ← REST API (POST /events/logs, /events/metrics)
│   Service       │
│  normalise →    │
│  index (OS) →   │
│  enqueue (MQ)   │
└────────┬────────┘
         │ BullMQ
         ▼
┌──────────────────────────────────────────┐
│              Core Platform               │
│ detect → deduplicate → correlate →       │
│ diagnose → notify → remediate            │
└──────────────────────────────────────────┘
         │
         ▼
┌─────────────────┐
│   Dashboard     │  ← SSE + REST
│   (Next.js 15)  │  ← Filtering, correlation, team mgmt
└─────────────────┘

Clean Architecture Layers

Each backend module follows a layered structure:

src/
├── domain/          Pure business logic, no framework imports
├── application/     Use cases that orchestrate domain + infrastructure
├── infrastructure/  Framework adapters (database, queue, HTTP clients)
└── interface/       Controllers, guards, DTOs (NestJS layer)
  • Domain: defines entities, value objects, and pure functions. Zero dependencies on NestJS, databases, or queues.
  • Application: use cases that wire domain logic with infrastructure ports. Injected via constructor.
  • Infrastructure: concrete adapters — OpenSearch client, BullMQ producer/consumer, PostgreSQL repositories, and external integration clients.
  • Interface: NestJS controllers, guards, and decorators. The thinnest possible layer.

Diagnostic investigations use the same layering: typed tool payloads in interface, policy/rate-limit/scoping in application, and safe connector calls in infrastructure with structured, audited outputs.

Shared Libraries

LibraryPurpose
@operyn/shared-typesZod schemas and TypeScript types for all domain events, incidents, remediations, and notifications
@operyn/connectorsFramework-free adapters: SlackNotifier, JiraClient, K8sClient, AwsDiagnosticsClient, PrometheusClient
@operyn/ai-orchestratorLangChain/LangGraph agent pipeline for multi-step AI diagnostic reasoning

Infrastructure

ComponentTechnologyPurpose
DatabasePostgreSQL 16Incident and remediation persistence
QueueRedis 7 (BullMQ)Async event processing and background jobs
SearchOpenSearch 2.11Log and metric indexing for full-text search

Design Principles

  • Domain isolation — business logic has zero framework dependencies.
  • Explicit dependencies — no hidden global state; everything is injected.
  • Optional integrations — Slack, Jira, etc. degrade gracefully when unconfigured.
  • Event-driven — ingestion and background workflows communicate via BullMQ.
  • Typed contracts@operyn/shared-types provides Zod-validated schemas as the single source of truth.

Authentication

The dashboard owns authentication: it uses better-auth (Next.js API route) for sign-in, sessions, and organization membership. core-platform accepts dashboard JWTs and internal service credentials for background flows. See Authentication and Roles and permissions for details.