This document illustrates various patterns for implementing database observability and proxy layers.
graph TB
subgraph "Application Layer"
APP[FastAPI App]
DEC[["@db_observer<br/>Decorator"]]
FUNC[Route Handler]
end
subgraph "Data Layer"
POOL[Connection Pool]
DB[(Database)]
end
subgraph "Observability"
LOG[Query Logger]
MET[Metrics Collector]
TRACE[Trace Storage]
end
APP --> FUNC
FUNC --> DEC
DEC --> POOL
POOL --> DB
DEC -.-> LOG
DEC -.-> MET
DEC -.-> TRACE
style DEC fill:#f9f,stroke:#333,stroke-width:4px
graph LR
subgraph "Request Flow"
REQ[HTTP Request] --> MW1[Auth Middleware]
MW1 --> MW2[Logging Middleware]
MW2 --> MW3[["DB Tracking<br/>Middleware"]]
MW3 --> ROUTE[Route Handler]
ROUTE --> DB[(Database)]
end
subgraph "Response Flow"
DB --> ROUTE2[Route Handler]
ROUTE2 --> MW3R[["DB Tracking<br/>Middleware"]]
MW3R --> MW2R[Logging Middleware]
MW2R --> MW1R[Auth Middleware]
MW1R --> RESP[HTTP Response]
end
subgraph "Metrics Collection"
MW3 -.-> METRICS[Query Metrics]
MW3R -.-> METRICS
METRICS --> DASH[Dashboard]
end
style MW3 fill:#f96,stroke:#333,stroke-width:4px
style MW3R fill:#f96,stroke:#333,stroke-width:4px
classDiagram
class BaseRepository {
<<abstract>>
+find(id)
+find_all()
+create(entity)
+update(entity)
+delete(id)
}
class ObservableRepository {
<<decorator>>
-repository: BaseRepository
-observer: QueryObserver
+find(id)
+find_all()
+create(entity)
+update(entity)
+delete(id)
-log_query(operation, params)
-measure_timing(operation)
}
class UserRepository {
+find_by_email(email)
+find_active_users()
}
class QueryObserver {
+before_query(context)
+after_query(context, result)
+on_error(context, error)
}
BaseRepository <|-- UserRepository
BaseRepository <|-- ObservableRepository
ObservableRepository o-- QueryObserver
ObservableRepository o-- BaseRepository
graph TB
subgraph "Application Tier"
APP1[FastAPI Instance 1]
APP2[FastAPI Instance 2]
APP3[FastAPI Instance 3]
end
subgraph "Proxy Layer"
PROXY[["Database Proxy<br/>:5433"]]
subgraph "Proxy Features"
QP[Query Parser]
QL[Query Logger]
QC[Query Cache]
CB[Circuit Breaker]
end
end
subgraph "Database Tier"
PRIMARY[(Primary DB<br/>:5432)]
REPLICA1[(Read Replica 1)]
REPLICA2[(Read Replica 2)]
end
subgraph "Observability Stack"
ES[Elasticsearch]
GRAF[Grafana]
PROM[Prometheus]
end
APP1 --> PROXY
APP2 --> PROXY
APP3 --> PROXY
PROXY --> QP
QP --> QL
QP --> QC
QP --> CB
CB --> PRIMARY
CB --> REPLICA1
CB --> REPLICA2
QL -.-> ES
PROXY -.-> PROM
ES -.-> GRAF
PROM -.-> GRAF
style PROXY fill:#9f9,stroke:#333,stroke-width:4px
graph TB
subgraph "Pod/Container Group"
subgraph "Application Container"
APP[FastAPI App<br/>:8000]
APPDB[DB Client]
end
subgraph "Sidecar Container"
SIDE[["DB Proxy Sidecar<br/>:5433"]]
LOG[Log Shipper]
METRIC[Metrics Agent]
TRACE[Trace Collector]
end
end
subgraph "External Services"
DB[(PostgreSQL<br/>:5432)]
LOGSTORE[Log Storage]
METRICSTORE[Metric Storage]
TRACESTORE[Trace Storage]
end
APP --> APPDB
APPDB -->|localhost:5433| SIDE
SIDE --> DB
SIDE --> LOG
SIDE --> METRIC
SIDE --> TRACE
LOG -.-> LOGSTORE
METRIC -.-> METRICSTORE
TRACE -.-> TRACESTORE
style SIDE fill:#ff9,stroke:#333,stroke-width:4px
graph TB
subgraph "Service A Pod"
APPA[FastAPI Service A]
SIDEA[["Envoy Proxy"]]
end
subgraph "Service B Pod"
APPB[FastAPI Service B]
SIDEB[["Envoy Proxy"]]
end
subgraph "Database Pod"
DBSIDE[["Envoy Proxy"]]
DB[(PostgreSQL)]
end
subgraph "Control Plane"
ISTIO[Istio Control Plane]
CONF[Configuration]
POLICY[Policies]
TELEM[Telemetry]
end
APPA --> SIDEA
SIDEA --> SIDEB
SIDEB --> APPB
APPB --> SIDEB
SIDEB --> DBSIDE
DBSIDE --> DB
ISTIO --> CONF
ISTIO --> POLICY
ISTIO --> TELEM
CONF -.-> SIDEA
CONF -.-> SIDEB
CONF -.-> DBSIDE
SIDEA -.-> TELEM
SIDEB -.-> TELEM
DBSIDE -.-> TELEM
style SIDEA fill:#9ff,stroke:#333,stroke-width:4px
style SIDEB fill:#9ff,stroke:#333,stroke-width:4px
style DBSIDE fill:#9ff,stroke:#333,stroke-width:4px
graph TB
subgraph "Application"
APP[FastAPI App]
WRITE[Write Operations]
READ[Read Operations]
end
subgraph "Smart Proxy Layer"
ROUTER[["Query Router<br/>:5433"]]
PARSER[SQL Parser]
CLASSIFIER[Query Classifier]
CACHE[Result Cache]
end
subgraph "Database Cluster"
PRIMARY[(Primary<br/>Write Only)]
REPLICA1[(Replica 1<br/>Read Only)]
REPLICA2[(Replica 2<br/>Read Only)]
REPLICA3[(Replica 3<br/>Read Only)]
end
subgraph "Monitoring"
LAG[Replication Lag Monitor]
HEALTH[Health Checker]
end
APP --> ROUTER
ROUTER --> PARSER
PARSER --> CLASSIFIER
CLASSIFIER -->|"INSERT/UPDATE/DELETE"| PRIMARY
CLASSIFIER -->|"SELECT"| CACHE
CACHE -->|"Cache Miss"| REPLICA1
CACHE -->|"Cache Miss"| REPLICA2
CACHE -->|"Cache Miss"| REPLICA3
PRIMARY -.->|Replication| REPLICA1
PRIMARY -.->|Replication| REPLICA2
PRIMARY -.->|Replication| REPLICA3
HEALTH --> PRIMARY
HEALTH --> REPLICA1
HEALTH --> REPLICA2
HEALTH --> REPLICA3
LAG --> REPLICA1
LAG --> REPLICA2
LAG --> REPLICA3
style ROUTER fill:#f99,stroke:#333,stroke-width:4px
style CLASSIFIER fill:#ff9,stroke:#333,stroke-width:4px
graph LR
subgraph "Application Layer"
APP[FastAPI App]
CMD[Command Handler]
QUERY[Query Handler]
end
subgraph "Proxy Layer"
CMDPROXY[["Command Proxy"]]
QUERYPROXY[["Query Proxy"]]
EVENTLOG[Event Logger]
end
subgraph "Storage"
EVENTSTORE[(Event Store)]
READMODEL[(Read Model)]
SNAPSHOT[(Snapshots)]
end
subgraph "Processors"
PROJ[Projection Builder]
REPLAY[Event Replayer]
end
APP --> CMD
APP --> QUERY
CMD --> CMDPROXY
CMDPROXY --> EVENTSTORE
CMDPROXY --> EVENTLOG
QUERY --> QUERYPROXY
QUERYPROXY --> READMODEL
EVENTSTORE --> PROJ
PROJ --> READMODEL
EVENTSTORE --> REPLAY
REPLAY --> SNAPSHOT
SNAPSHOT --> READMODEL
style CMDPROXY fill:#9f9,stroke:#333,stroke-width:4px
style QUERYPROXY fill:#99f,stroke:#333,stroke-width:4px
graph TB
subgraph "Request Pipeline"
REQ[Database Request]
H1[["Auth Handler"]]
H2[["Rate Limiter"]]
H3[["Query Validator"]]
H4[["Cache Handler"]]
H5[["Logger Handler"]]
H6[["Executor Handler"]]
REQ --> H1
H1 -->|pass| H2
H2 -->|pass| H3
H3 -->|pass| H4
H4 -->|miss| H5
H5 -->|pass| H6
H6 --> DB[(Database)]
H1 -->|reject| ERR1[401 Unauthorized]
H2 -->|reject| ERR2[429 Too Many Requests]
H3 -->|reject| ERR3[400 Bad Query]
H4 -->|hit| RESP[Cached Response]
end
subgraph "Response Pipeline"
DB --> R6[["Executor Handler"]]
R6 --> R5[["Logger Handler"]]
R5 --> R4[["Cache Handler"]]
R4 --> R3[["Transformer"]]
R3 --> R2[["Metrics Handler"]]
R2 --> R1[["Response Builder"]]
R1 --> RESULT[Final Response]
end
style H1 fill:#f99,stroke:#333,stroke-width:2px
style H2 fill:#f99,stroke:#333,stroke-width:2px
style H3 fill:#f99,stroke:#333,stroke-width:2px
style H4 fill:#9f9,stroke:#333,stroke-width:2px
style H5 fill:#99f,stroke:#333,stroke-width:2px
style H6 fill:#fff,stroke:#333,stroke-width:2px
graph TB
subgraph "Service A"
SA[FastAPI Service A]
SPA[["Span Creator"]]
end
subgraph "Service B"
SB[FastAPI Service B]
SPB[["Span Creator"]]
end
subgraph "Database Proxy"
PROXY[["Observability Proxy"]]
SPDB[["DB Span Creator"]]
QUERY[Query Analyzer]
TIMING[Timing Collector]
end
subgraph "Database"
DB[(PostgreSQL)]
EXPLAIN[Query Planner]
end
subgraph "Tracing Infrastructure"
JAEGER[Jaeger Collector]
UI[Jaeger UI]
end
SA --> SPA
SPA -->|"TraceID: 123"| SB
SB --> SPB
SPB -->|"TraceID: 123"| PROXY
PROXY --> SPDB
SPDB --> QUERY
QUERY --> TIMING
TIMING --> DB
DB --> EXPLAIN
SPA -.->|"Span: service-a"| JAEGER
SPB -.->|"Span: service-b"| JAEGER
SPDB -.->|"Span: db-query"| JAEGER
TIMING -.->|"Timing Metrics"| JAEGER
EXPLAIN -.->|"Query Plan"| JAEGER
JAEGER --> UI
style PROXY fill:#f9f,stroke:#333,stroke-width:4px
style SPDB fill:#ff9,stroke:#333,stroke-width:2px
graph TB
subgraph "Application"
APP[FastAPI App]
end
subgraph "Monitoring Proxy"
PROXY[["Performance Proxy"]]
subgraph "Analyzers"
QA[Query Analyzer]
PA[Plan Analyzer]
IA[Index Advisor]
SA[Slow Query Logger]
end
end
subgraph "Database"
DB[(PostgreSQL)]
STATS[pg_stat_statements]
PLANS[Query Plans]
end
subgraph "Alerting"
ALERT[Alert Manager]
SLACK[Slack]
PAGE[PagerDuty]
DASH[Dashboard]
end
APP --> PROXY
PROXY --> QA
QA --> PA
PA --> IA
QA --> SA
PA --> DB
DB --> PLANS
DB --> STATS
SA -->|"Query > 1s"| ALERT
IA -->|"Missing Index"| ALERT
PA -->|"Full Scan"| ALERT
ALERT --> SLACK
ALERT --> PAGE
ALERT --> DASH
STATS -.-> DASH
style PROXY fill:#9ff,stroke:#333,stroke-width:4px
graph TB
subgraph "Development"
APPDEV[FastAPI Dev]
PROXYDEV[["Simple Proxy<br/>Verbose Logging"]]
DBDEV[(Local PostgreSQL)]
end
subgraph "Staging"
APPSTG[FastAPI Staging]
PROXYSTG[["Observability Proxy<br/>Sampling: 10%"]]
DBSTG[(Staging PostgreSQL)]
REPLAY[Query Replayer]
end
subgraph "Production"
APPPROD1[FastAPI Prod 1]
APPPROD2[FastAPI Prod 2]
APPPROD3[FastAPI Prod 3]
LB[Load Balancer]
PROXYPROD[["HA Proxy Cluster<br/>Sampling: 1%"]]
DBPROD[(Production PostgreSQL)]
end
subgraph "Observability Platform"
COLLECT[Collector]
STORE[Time Series DB]
ANALYZE[Analytics Engine]
ML[ML Anomaly Detection]
end
APPDEV --> PROXYDEV --> DBDEV
APPSTG --> PROXYSTG --> DBSTG
LB --> APPPROD1
LB --> APPPROD2
LB --> APPPROD3
APPPROD1 --> PROXYPROD
APPPROD2 --> PROXYPROD
APPPROD3 --> PROXYPROD
PROXYPROD --> DBPROD
PROXYDEV -.-> COLLECT
PROXYSTG -.-> COLLECT
PROXYPROD -.-> COLLECT
COLLECT --> STORE
STORE --> ANALYZE
ANALYZE --> ML
REPLAY -.->|"Replay Prod Queries"| PROXYSTG
style PROXYDEV fill:#9f9,stroke:#333,stroke-width:2px
style PROXYSTG fill:#ff9,stroke:#333,stroke-width:2px
style PROXYPROD fill:#f99,stroke:#333,stroke-width:4px