Cloud and AI Architecture: Case Studies · Part 3 of 4
Sentrio
A Series A security-operations platform and its architecture on AWS, GCP, and Azure.
The company
Sentrio helps security operations center (SOC) teams triage and investigate alerts faster. It ingests signals from a customer's existing logs, security tools, and alert streams, uses AI to correlate related signals into a single incident, summarizes what happened in plain language, and suggests next investigative steps. Analysis that used to take an analyst twenty minutes of manual log correlation now takes a few. The SOC team stays in place; what shrinks is the time each analyst spends on the repetitive parts of triage.
The company has grown to fifty to a hundred employees, twenty-five to forty of them engineers. It has meaningful annual recurring revenue and hundreds to low thousands of customers, and it's past the product-market-fit question that dominated its first two years: the product works, teams use it, and it's raised a Series A on the strength of that traction. What's changed is who's buying. The security teams that adopted Sentrio first were small, willing to try something new, and empowered to buy it themselves. The enterprise teams asking to buy in now are large, risk-averse, and several approvals away from a purchase order. They arrive with a security questionnaire, a procurement process, and a list of things the product has to do before anyone signs: single sign-on, audit logging, and a commitment about which country their data sits in.
Usage pattern
Two kinds of traffic, with different shapes.
Alert ingestion is continuous and uneven. Every customer streams logs and alerts in around the clock, at a baseline that scales with the size of their environment. On top of that baseline sit sharp, unpredictable spikes: an active intrusion, a misconfigured logging rule, a noisy deployment. A single customer's volume can jump fiftyfold for a few hours with no warning. Those spikes are usually independent of each other, but not always. When a widely exploited vulnerability lands, every customer spikes on the same afternoon, which is the load case worth designing for.
Analyst-facing queries follow shift patterns. SOC teams work around the clock, so there's no quiet window in aggregate, though any single customer's dashboard traffic concentrates during their own daytime hours. Query load is modest next to ingestion volume, and it's the half that a human is waiting on, so it gets priority when the two compete for the same database.
The asymmetry drives much of the design below. Ingestion has to absorb a burst without dropping data and without slowing the queries an analyst is running mid-investigation.
What's new since pre-seed and seed
The technical work at pre-seed is building something that works. The technical work at Series A is making it survivable by someone else's standards. Three things change.
First, the buyer changes, and the buyer brings requirements that have nothing to do with whether the product is good: federated identity, retained audit trails, a documented answer to where data lives. Second, load stops being predictable. Early customers generate traffic in proportion to their size; enterprise customers generate traffic in proportion to whatever is happening in their environment that day. Third, the team gets large enough that coordination becomes a real cost, which is what turns infrastructure-as-code and a deployment pipeline from good hygiene into a hard requirement.
Requirements
Functional
- Continuous alert and log ingestion from each customer's existing security tooling, absorbing bursts without dropping or reordering data an investigation might depend on.
- AI correlation and summarization: related signals grouped into one incident, summarized in plain language, with suggested next investigative steps.
- Full-text and structured search across a customer's ingested log and alert history, fast enough to use during a live investigation.
- Single sign-on: customers provision and de-provision Sentrio access through their own identity provider, so an employee removed from their directory loses access the same day.
- Audit logging: who accessed which customer's data, when, and what they did with it, retained and queryable for the customer's own compliance obligations as well as Sentrio's.
- Multi-tenant isolation strong enough to hold up when an enterprise security team asks pointed questions about how it works.
- Regional deployment: a customer whose contract requires their data to stay in a given country gets a deployment that keeps it there.
- Customer-facing analytics: incident trends, mean time to triage, and the reporting a SOC manager takes to their own leadership.
- Continuous model evaluation: a measured answer to whether correlation and summarization quality is holding, sampled from real traffic rather than a fixed test set, because the attack techniques the model has to summarize change month to month.
Non-functional
- Reliability approaching a contractual SLA. A SOC team depends on this during an active incident. An outage leaves a customer triaging by hand while an attack is under way, and enterprise contracts increasingly put a number on how often that's allowed to happen.
- Throughput headroom for a correlated spike, meaning the ingestion path stays ahead when many customers surge at once, rather than when one does.
- Query latency under load: an analyst's search stays responsive while ingestion is at peak, since those are the same moments.
- Regional data residency for customers who require it, which means supporting more than one deployment region even while most customers don't need it.
- Auditability: every access to customer data reconstructable after the fact, both as SOC 2 evidence and as input to a customer's own investigation.
- Tested disaster recovery: a stated recovery point and recovery time objective, with a restore drill that confirms the numbers are still true.
- Managed inference cost: LLM spend scales with alert volume, which customers control and Sentrio doesn't, so cost per incident has to be tracked as a unit economic rather than reviewed at the end of the month.
Compliance
Enterprise customers, particularly in regulated industries, will ask about SOC 2 (a report on Sentrio's own security controls), GDPR (if any customer or their end users are in the EU), and potentially HIPAA, since a healthcare organization's security logs can carry health-adjacent signals from its own environment.
Major risks
Enterprise trust risk is now dominant. A single visible security incident, or failing one large customer's security review, costs more at this stage than a slow month of usage would. The system has to hold up technically and in front of a security team looking for reasons to say no.
Reliability risk has grown alongside the customer base. A SOC team's dependence on this product during active incidents means an outage has a sharper cost than it did when usage was lighter and less time-sensitive. Reliability engineering, covered in Reliability and Distributed Systems, stops being optional at this stage.
Concentration risk appears for the first time. At hundreds of customers with enterprise pricing, a handful of accounts can represent a large share of revenue, and each of them has a security team with standing to demand an architectural change. That gives a single customer leverage over the roadmap that no customer had a year ago.
Architecture: AWS
The requirements above pull in two directions. Enterprise buyers want SSO, audit trails, regional deployment, and an SLA. The traffic pattern wants an ingestion path that absorbs a correlated spike. And the company is now large enough that platform investment pays for itself. "Reach for the most managed option in every category" is still the right instinct, with more places where it needs an argument.
flowchart TB U[Analyst's
browser] --> CF[CloudFront + WAF,
S3 static frontend] U --> ALB[ALB] ALB --> ECS[ECS on Fargate:
API] ECS --> BR[Bedrock:
model routing] ECS --> PLAT[Cognito +
enterprise SSO
Secrets Manager
CloudWatch + X-Ray] ECS ~~~ ALERTS[Customer log /
alert feeds] ALERTS --> KDS[Kinesis
Data Streams] KDS --> ECSW[ECS on Fargate:
correlation workers] ECSW --> REDIS[(ElastiCache
Valkey)] ECSW --> AUR[(Aurora Postgres
writer + reader
in a second AZ)] ECS --> AUR ECSW --> OS[(OpenSearch:
log search)] ECSW --> S3L[S3: raw
log archive] OS ~~~ S3L AUR -->|export| RS[(Redshift Serverless:
analytics)]
Frontend and API
The frontend is still static, served from S3 behind CloudFront, now with AWS WAF attached to CloudFront and to the load balancer in front of the API, an addition earned once the customer base includes enterprises whose security reviews ask about edge protection directly. The API layer moves from Lambda to ECS on Fargate behind an Application Load Balancer.
Why a managed container platform instead of Kubernetes?
Twenty-five to forty engineers is enough people to start feeling Lambda's per-function fragmentation, and still not enough workload diversity to justify Kubernetes' scheduling flexibility and the operational cost of running EKS well. ECS on Fargate sits in between: full containers and long-lived services, without a Kubernetes control plane and the tooling around it for a team that doesn't need it yet. Compute Options covers this decision framework in general terms. The ADRs below set the condition for revisiting it.
SSO and audit logging
Cognito federates to each enterprise customer's own identity provider over SAML or OIDC, so a customer's security team can provision and de-provision Sentrio access through the same system they already use for every other vendor, instead of Sentrio maintaining a second, separate set of credentials. Every access to customer data is written to an application-level audit log table in Aurora, distinct from CloudTrail's infrastructure-level audit trail: CloudTrail answers "who called which AWS API," the audit log table answers "which analyst viewed which customer's incident," which is the question both Sentrio's own SOC 2 evidence and a customer's own investigation need answered.
Alert ingestion (event-driven)
Customer log and alert feeds arrive continuously, around the clock, with the bursts described in the usage pattern above. Kinesis Data Streams ingests that continuous flow, and a fleet of ECS on Fargate correlation workers consumes from it: enriching each alert, correlating it against related signals, and writing the result to Aurora and to OpenSearch. Kinesis keeps records in order within a shard (partitioned by customer, say) and retains them for replay, which fits this better than a plain queue: a burst during an active incident has to be processed in order, and a slow consumer or a bad deploy can be re-run from the stream instead of losing alerts. See Messaging and Event-Driven Architecture for the general trade-offs between a queue and a stream.
Database and caching
Aurora PostgreSQL now runs a writer plus at least one reader instance in a second availability zone. The reader is both the failover target (Aurora promotes it if the writer fails) and the place read-heavy customer dashboards and internal analytics queries run, which keeps that traffic off the writer the ingestion pipeline is using. A single-instance cluster also keeps its storage across multiple AZs, but it recreates a failed writer in the same AZ (typically under ten minutes) and needs a new instance created by hand after an AZ outage. ElastiCache (Valkey or Redis OSS) caches hot-path lookups the correlation workers hit repeatedly (recent alert context, rate-limit counters, session data), work that would otherwise mean repeated round trips to the database for the same small set of records. This is the caching pattern covered generally in Caching.
Object storage and log search
Raw ingested logs are archived to S3, which is cheap enough per terabyte to keep years of them. Full-text search across alert and log data now runs on OpenSearch, separate from the RAG vector store: OpenSearch is built for this kind of high-volume, full-text and structured log search, where Aurora's pgvector extension remains the right tool for the narrower job of semantic search over a knowledge base of playbooks and threat-intelligence documents. Two different search problems, kept in two engines.
LLM and model routing
Sentrio calls Bedrock, but no longer against a single model for every request. A routing layer sends complex incident summarization and reasoning to a stronger, more expensive model, and simpler, high-volume tasks (formatting, basic classification) to a faster, cheaper one. Across millions of monthly requests, the price difference between tiers is large enough to pay for the routing logic several times over.
RAG evaluation
A scheduled evaluation job runs a held-out set of real (anonymized) past incidents through the current retrieval-and-summarization pipeline and scores the output against a known-good answer, tracking those scores over time so a model or prompt change can be checked against a regression before it ships. Bedrock's RAG evaluation jobs take a dataset with expected answers and score retrieval and generated responses, and its model evaluation jobs can use a judge model; Sentrio's own automation starts the jobs on a schedule. Production traffic is sampled into that set continuously, which matters here more than a fixed suite would: the attack techniques the model summarizes change month to month, and a test set frozen a year ago stops representing the job. See Evaluating AI Systems.
Analytics, cost monitoring, and disaster recovery
Redshift Serverless now backs both customer-facing incident analytics and internal product and model-performance metrics, fed by a straightforward export pipeline from Aurora and the evaluation pipeline above. At this data volume, running those queries directly against the operational database would put reporting load in competition with the ingestion pipeline. Cost monitoring runs on AWS Cost Explorer and Budgets, with resources tagged by team and, where practical, by tenant, so a cost spike can be traced to its cause rather than showing up only as a bigger total bill.
Sentrio also deploys to more than one AWS region as separate regional deployments rather than one active-active system spanning regions, so a customer requiring EU data residency lands entirely within an EU region. That's regional choice for data residency, distinct from multi-region resilience for a single tenant (see Regions, AZs, and Edge). Disaster recovery within each region is a documented, tested plan: automated Aurora backups copied to a second region, Terraform to rebuild the stack there, a defined recovery time objective and recovery point objective, and a periodic restore drill, rather than an untested assumption that the backups would restore cleanly.
CI/CD and infrastructure as code
Every environment is defined in Terraform, and deploys run through a CI/CD pipeline (CodePipeline and CodeBuild, or GitHub Actions targeting ECS) rather than a hand-run script. With twenty-five to forty engineers touching this system, undocumented infrastructure and manual deploys stop being a shortcut and start being a source of drift and incidents. Infrastructure as Code and Delivery covers the general reasoning.
Identity, secrets, and monitoring
IAM roles remain scoped per service to least privilege, the granularity an enterprise security review checks for now that Sentrio's customers are SOC teams. Secrets Manager continues to hold credentials and API keys, so nothing sensitive sits in an environment variable an auditor could quote back as a finding. CloudWatch and X-Ray, with services instrumented through OpenTelemetry (AWS put the X-Ray SDKs in maintenance mode in February 2026), now cover distributed tracing across the ECS services and the Kinesis pipeline, answering "which of these five services is slow" where single-function logs could only say "something is slow."
Architecture: GCP
Same requirements. A couple of decisions land in a different place on GCP than they did on AWS, beyond a change of product name.
flowchart TB U[Analyst's
browser] --> LB[Global external
Application LB:
Cloud CDN + Cloud Armor] LB --> GCS_F[Cloud Storage
frontend] LB --> RUN[Cloud Run: API] RUN --> VTX["Gemini Enterprise
Agent Platform
(formerly Vertex AI):
model routing"] RUN --> PLAT["Identity Platform
(SAML / OIDC)
Secret Manager
Cloud Logging /
Monitoring / Trace"] RUN ~~~ ALERTS[Customer log /
alert feeds] ALERTS --> PS[Pub/Sub] PS --> RUNW[Cloud Run:
correlation workers,
push subscription] RUNW --> MEM[(Memorystore
Redis)] RUNW --> ADB[(AlloyDB
primary +
read pool)] RUN --> ADB RUNW --> BQ[(BigQuery:
log search +
analytics)] RUNW --> GCS_L[Cloud Storage:
raw log archive] BQ ~~~ GCS_L
The frontend stays on Cloud Storage behind Cloud CDN, now with Cloud Armor for the same reason AWS added WAF: enterprise security reviews expect edge protection. Cloud CDN and Cloud Armor both attach to the global external Application Load Balancer, so the API's Cloud Run service sits behind that same load balancer (with its ingress restricted to it) rather than being reached directly on its run.app URL.
Why Cloud Run still, instead of GKE, even at this scale?
GCP's service model diverges from the AWS design here. On AWS, the correlation-worker fleet runs on ECS on Fargate because Lambda's request-response model fits a continuously-consuming stream processor poorly. On GCP, Pub/Sub supports push subscriptions that invoke a Cloud Run service directly for each message, which means Cloud Run can absorb the correlation-worker role the same way it absorbs the API role, without introducing a second compute platform at all. Where AWS's answer to "more workload diversity" was "add ECS alongside Lambda," GCP's answer is "Cloud Run already covers this." GKE Autopilot remains the right call once a workload needs long-lived, stateful processing that doesn't fit a request- or push-driven model, which isn't the case here yet.
SSO and audit logging
Identity Platform is Google's customer identity service for application end users. It federates to each enterprise customer's own SAML or OIDC provider, and its multi-tenancy support keeps each customer's users and provider configuration in a separate tenant. Workforce Identity Federation is a different product, for Sentrio's own employees to reach Google Cloud, so it plays no part in the analysts' sign-in. Cloud Audit Logs plus an application-level audit table in AlloyDB give the same infrastructure-level/application-level split as the AWS design.
Alert ingestion (event-driven)
Pub/Sub ingests the continuous stream of customer log and alert feeds, with the correlation workers subscribed via push subscription as described above. Same event-driven shape as Kinesis on AWS, with a different delivery model underneath: Pub/Sub delivers messages to subscribers (here by push) and scales without shards to manage, where Kinesis is a stream a consumer polls shard by shard. See Messaging and Event-Driven Architecture for the distinction. Ordering is opt-in: publishing with the customer ID as an ordering key keeps each customer's alerts in order, at the cost of serializing delivery per key, and a subscription can retain acknowledged messages for replay.
Database and caching: AlloyDB
AlloyDB is the choice over Cloud SQL here because the dashboards run analytical queries against the same database that takes ingestion writes, which is what AlloyDB's columnar engine is built to speed up, and because it offers the ScaNN vector index for the RAG knowledge base of playbooks and threat intelligence. Cloud SQL for PostgreSQL with read replicas would also work and costs less, so this is a judgment call that depends on measured dashboard and vector-search latency. AlloyDB's primary has high availability with a standby in another zone by default. A read pool handles the dashboard and analytics load, keeping it off the primary the ingestion pipeline writes to, the same role the reader plays in the AWS design. Memorystore for Redis caches the same hot-path lookups ElastiCache handles on AWS.
Log search and analytics: BigQuery does both jobs
A second divergence from the AWS design. On AWS, full-text log search (OpenSearch) and analytics (Redshift) are two separate services solving two separate problems. On GCP, BigQuery does both: it handles high-volume, structured and semi-structured data, supports search indexes for text lookups, and is already the natural home for analytics and reporting. BigQuery's search indexes are documented for point lookups, with no fuzzy matching or wildcards, and Google publishes no latency figures for them, so both the query shapes analysts need and the response time need testing against the "responsive during a live investigation" requirement. Sentrio's GCP design routes ingested logs and alerts into BigQuery once, and both the log-search use case and the analytics use case query the same tables. One capability maps to two services on AWS and to one on GCP.
LLM and model routing
Gemini Enterprise Agent Platform (formerly Vertex AI) routes between Gemini model tiers, a faster, cheaper tier for high-volume simple tasks and a stronger tier for complex incident reasoning, the same routing instinct as Bedrock's on AWS, reasoned from the platform's own tiered model family.
RAG evaluation, cost monitoring, and disaster recovery
A scheduled evaluation pipeline built on the platform's evaluation tooling runs the same held-out real-incident test set as the AWS design and tracks the same metrics over time. Cloud Billing budgets and resource labels track spend by team and tenant, and Sentrio deploys to separate GCP regions for customers needing specific data residency, the same regional-choice pattern as AWS. Disaster recovery is built on AlloyDB's automated backups (replicated to a second region), Terraform to rebuild there, and the zone redundancy within each region, with the same recovery-objective and restore-drill discipline as the AWS design.
CI/CD and infrastructure as code
Every environment is defined in Terraform, deployed through Cloud Build or GitHub Actions targeting Cloud Run, matching the discipline the AWS design adopts at this stage for the same reason: a team this size can't safely rely on hand-run deploys.
Identity, secrets, and monitoring
IAM roles remain scoped per Cloud Run service to least privilege. Secret Manager continues to hold credentials. Cloud Logging, Cloud Monitoring, and Cloud Trace now cover distributed tracing across the Cloud Run services and Pub/Sub pipeline.
Architecture: Azure
Same requirements again. Azure shares GCP's instinct to avoid a second compute platform and reaches it through a different mechanism, and it carries one advantage specific to a security product's customer base.
flowchart TB U[Analyst's
browser] --> FD[Front Door Premium
+ WAF policy] FD --> BLOB_F[Blob Storage
frontend] FD --> CA[Container Apps:
API] CA --> AOAI[Azure OpenAI:
model routing] CA --> PLAT["Entra ID (multitenant app) +
Entra External ID
Key Vault
Azure Monitor /
App Insights"] CA ~~~ ALERTS[Customer log /
alert feeds] ALERTS --> EH[Event Hubs] EH --> CAW[Container Apps:
correlation workers,
KEDA-scaled] CAW --> REDIS[(Azure Managed
Redis)] CAW --> PG[(Azure DB for
PostgreSQL Flexible
Server, zone-redundant HA
+ read replica)] CA --> PG CAW --> ADX[(Azure Data Explorer:
log search +
analytics)] CAW --> BLOB_L[Blob Storage:
raw log archive] ADX ~~~ BLOB_L
The frontend stays on Blob Storage behind Front Door, now with a WAF policy attached. The managed rule sets that a security review usually asks about require the Premium tier; Standard allows only custom rules. As on GCP, the API's Container Apps environment sits behind Front Door too.
Why Container Apps still, instead of AKS, even at this scale?
Both AWS and GCP faced this same fork, and each cloud's own service model produced a different answer. AWS added a second compute platform (ECS) because Lambda's request-response shape doesn't fit a continuously-consuming stream processor. GCP kept a single platform because Cloud Run can be invoked directly via Pub/Sub push subscriptions. Azure also keeps a single platform, but through a third mechanism: Container Apps is built on KEDA, which can scale the number of running replicas up and down based on how far an Event Hubs consumer group is behind, as well as on HTTP request volume. The correlation workers still run as a polling consumer process, unlike Cloud Run's push-invoked model, and replicas beyond the number of Event Hubs partitions sit idle, so the partition count caps scale-out. GCP and Azure both reach "no second platform needed"; AWS's answer required one.
SSO and audit logging
Sentrio registers its app as a multitenant application in Entra ID, so customers that already run Entra ID (or its predecessor, Azure AD) can consent to it in their own tenant and have their analysts sign in with the directory they already administer. Entra External ID covers customers on other identity providers, which it federates to over SAML, WS-Federation, or OIDC. Entra-using customers are a large share of enterprise security teams, and for them this tends to make the security review easier. The advantage is specific to this customer base. Azure Monitor Activity Logs plus an application-level audit table in the Postgres database give the same infrastructure/application split used on the other two clouds.
Alert ingestion (event-driven)
Event Hubs ingests the continuous stream of customer log and alert feeds, Azure's high-throughput streaming ingestion product, playing the same role as Kinesis on AWS. The KEDA-scaled Container Apps workers described above consume from it, correlate and enrich each alert, and write results onward.
Database and caching
Azure Database for PostgreSQL Flexible Server runs with zone-redundant high availability, which keeps a synchronous standby in a second zone and fails over automatically; this is a setting to turn on, not the default. A read replica absorbs dashboard and analytics load, keeping it off the primary. Replicas are asynchronous and promoted manually, so they do not replace the standby. GCP and Azure diverge here: the AlloyDB option on GCP is a different engine, while Flexible Server scales by raising compute size and adding replicas on the same engine. Azure Managed Redis (which replaces Azure Cache for Redis) caches the same hot-path lookups ElastiCache and Memorystore handle on the other two clouds.
Log search and analytics: Azure Data Explorer
Azure Data Explorer (Kusto/ADX) is the choice here over Synapse. ADX is built for high-volume, time-series log and event data, queried with KQL, the same query language Microsoft Sentinel uses over Log Analytics. Ingested alerts and logs land in ADX once, and both log search and analytics reporting query the same tables, the "one service, two jobs" shape BigQuery plays on GCP. Microsoft Fabric's Real-Time Intelligence (Eventhouse) offers the same Kusto engine as a SaaS service and may be the better starting point for a new build, while Fabric or Synapse suit broader business intelligence reporting if that need grows separately.
LLM and model routing
Azure OpenAI, accessed through Microsoft Foundry (formerly Azure AI Foundry), routes between model tiers the same way Bedrock and Gemini Enterprise Agent Platform do on the other two clouds: a stronger tier for complex incident reasoning, a faster and cheaper tier for high-volume simple tasks.
RAG evaluation, cost monitoring, and disaster recovery
Microsoft Foundry's evaluation tooling runs the same held-out real-incident test set as the other two clouds. Azure Cost Management with budgets and resource tags tracks spend by team and tenant, and Sentrio deploys to separate Azure regions for customers needing specific data residency, the same regional-choice pattern as AWS and GCP. Disaster recovery relies on Flexible Server's automated backups with geo-redundant storage enabled and Terraform to rebuild in another region, with the same recovery-objective and restore-drill discipline as the other two designs.
CI/CD and infrastructure as code
Environments are defined in Terraform (or Bicep, where a team prefers Azure's native IaC language), deployed through Azure DevOps or GitHub Actions targeting Container Apps, matching the same discipline adopted on the other two clouds at this stage.
Identity, secrets, and monitoring
Managed identities on each Container Apps service remain scoped to least privilege. Key Vault continues to hold secrets. Azure Monitor and Application Insights now cover distributed tracing across the Container Apps services and Event Hubs pipeline.
Capability comparison
| Capability | AWS | GCP | Azure | Decision rationale |
|---|---|---|---|---|
| DNS | Route 53 | Cloud DNS | Azure DNS | A thin, interchangeable layer. |
| CDN + edge protection | CloudFront + WAF | Cloud CDN + Cloud Armor, on the global external Application Load Balancer | Front Door Premium + WAF policy | WAF added on all three, because enterprise security reviews expect it. |
| Load balancing | Application Load Balancer, with WAF attached | Global external Application Load Balancer in front of Cloud Run | Front Door in front of Container Apps' built-in ingress | With edge protection required, GCP needs an explicit load balancer; Azure's Front Door fills that role. |
| Compute (API + workers) | ECS on Fargate | Cloud Run | Container Apps | No Kubernetes on any cloud; see the ADR below. |
| Kubernetes | EKS | GKE | AKS | Deliberately unused; see the ADR below. |
| Relational database | Aurora PostgreSQL, writer + reader in a second AZ | AlloyDB, HA primary + read pool | Azure DB for PostgreSQL Flexible Server, zone-redundant HA + read replica | Multi-AZ failover comes from the second-zone reader, HA standby, or HA setting. GCP moves to AlloyDB (Cloud SQL would also work). |
| NoSQL database | DynamoDB | Firestore | Cosmos DB | Not used: relational, vector, and log-native engines cover the access patterns. |
| Cache | ElastiCache (Valkey or Redis OSS) | Memorystore for Redis | Azure Managed Redis (replaces Azure Cache for Redis) | New on all three: the correlation workers re-read the same small set of records. |
| Object storage | S3 | Cloud Storage | Blob Storage | Raw log and alert archive; near-equivalent. |
| Streaming ingestion | Kinesis Data Streams | Pub/Sub | Event Hubs | Different delivery models: Kinesis shards a consumer polls; Pub/Sub push with ordering keys and replay; Event Hubs partitions a KEDA-scaled consumer polls. |
| Event bus / fan-out | EventBridge | Pub/Sub (same product as above) | Event Grid | Not needed: each ingestion pipeline has one consumer type. |
| Secrets | Secrets Manager | Secret Manager | Key Vault | Equivalent. |
| IAM and SSO | IAM + Cognito with SAML/OIDC federation | Cloud IAM + Identity Platform with SAML/OIDC federation | Entra ID (multitenant app) + Entra External ID | All federate sign-in to a customer's own identity provider; Azure has an edge with customers already on Entra ID. |
| Observability | CloudWatch + X-Ray | Cloud Logging / Monitoring / Trace | Azure Monitor + Application Insights | Distributed tracing is now included on all three. |
| Log search + analytics | OpenSearch (search) + Redshift Serverless (analytics), two services | BigQuery, one service for both | Azure Data Explorer, one service built for log-shaped data | Different shapes: two services on AWS, one on GCP, one log-oriented service on Azure. |
| LLM platform | Bedrock, with model routing across tiers | Gemini Enterprise Agent Platform (formerly Vertex AI), with model routing across Gemini tiers | Azure OpenAI via Microsoft Foundry (formerly Azure AI Foundry), with model routing across tiers | All three now route by task complexity. |
| Vector search | pgvector on Aurora | pgvector with ScaNN indexing on AlloyDB | pgvector on Azure DB for PostgreSQL | A vector extension on the existing database covers the RAG knowledge base; AlloyDB's index is a small GCP-specific edge. |
| RAG evaluation | Bedrock evaluation features, run on a schedule | Gemini Enterprise Agent Platform evaluation tooling | Microsoft Foundry evaluation tooling | Scored against held-out incidents, with production traffic sampled in. |
| GPU / accelerator infrastructure | None provisioned | None provisioned | None provisioned | Abstracted by the managed LLM platforms. |
Architecture decision records
Decision
Use a managed container platform (ECS on Fargate, Cloud Run, or Container Apps) instead of Kubernetes, for now.
Why
Each cloud's own primitives (ECS task definitions, Cloud Run's Pub/Sub push integration, Container Apps' KEDA scaling) already cover the workload diversity Sentrio has today, and no workload on any of the three needs Kubernetes-level scheduling control.
Alternatives considered
- Managed Kubernetes (EKS/GKE/AKS) on all three: more flexibility than currently needed, at an ongoing operational cost.
Trade-off
Less control over fine-grained scheduling and networking than Kubernetes offers. That flexibility has no current use, and the revisit condition below keeps the decision open.
Revisit when
Workload diversity grows enough (more independent services, more varied resource profiles) that a managed container platform's simpler model starts constraining rather than helping.
Decision
Continue with a shared database and row-level, tenant-ID-scoped isolation instead of separate databases per customer.
Why
Hundreds to low thousands of customers make per-tenant databases an operational multiplier the team can't absorb. Row-level isolation enforced at the identity layer, the query layer, and the search engine's own access controls has held up in the enterprise security reviews to date.
Alternatives considered
- Per-tenant database instances for the largest enterprise accounts specifically: stronger isolation story for the customers most likely to ask for it, at added operational cost for a subset of customers.
Trade-off
The largest enterprise customers sometimes ask during due diligence whether their data is "physically separated." The answer is no, which makes those sales conversations harder than a per-tenant model would.
Revisit when
A large enough contract specifically requires physical isolation as a condition of signing, or the shared-schema model becomes an operational bottleneck independent of any single customer's request.
Decision
Deploy multi-AZ within each region instead of multi-region active-active.
Why
Regional deployment for data residency is now a firm requirement. Resilience against a full regional outage is a different problem, and multi-AZ within a region already covers the far more common failure mode (a single zone or host going down) at a fraction of the operational cost of active-active replication across regions.
Alternatives considered
- Multi-region active-active per deployment region: the strongest resilience posture, and complex enough that it belongs to a later stage with a dedicated platform team.
- Cross-region backup copies plus Terraform, to rebuild in another region after a regional loss: much cheaper than a standing second region, and the usual disaster-recovery plan at this size.
Trade-off
A full regional outage still takes that region's customers offline until it resolves or until a rebuild from backups finishes. That is an accepted risk at this stage. Multi-AZ also costs something: the database needs a second-zone reader or standby (see the database sections above), and the stateless services need to run in at least two zones.
Revisit when
An enterprise contract's SLA specifically requires surviving a full regional outage with no downtime.
Decision
Buy a managed model-evaluation tool (each cloud's own AI evaluation offering) instead of building an in-house evaluation framework.
Why
Building a correctness-and-groundedness evaluation harness from scratch is ongoing engineering work with no direct customer-facing payoff; each cloud's managed evaluation tooling already covers the core need (scoring model output against held-out examples, tracking regressions over time) well enough to start from.
Alternatives considered
- A custom-built evaluation pipeline: full control over scoring criteria, at the cost of engineering time better spent on the product itself.
Trade-off
Less control over exactly how evaluation scoring works than a fully custom pipeline would give. For the current need, that control isn't yet worth its engineering cost.
Revisit when
Evaluation needs grow specific enough (a scoring dimension unique to security-incident correctness, say) that the managed tooling's built-in criteria stop being an adequate fit.
Decision
Ingest customer alerts through a streaming platform (Kinesis, Pub/Sub, or Event Hubs) instead of a simple point-to-point queue.
Why
Alert volume is now continuous rather than triggered by a single user action, and a streaming platform orders records within a partition and retains them for replay, which a standard queue does not (a FIFO queue orders but cannot replay), and that matters when a burst of related alerts during an active incident needs to be processed coherently.
Alternatives considered
- A simple managed queue (SQS, Cloud Tasks, or Service Bus): less to operate, with weaker ordering and replay guarantees under sustained, high-volume load.
Trade-off
A streaming platform is a heavier abstraction to operate correctly (consumer groups, checkpointing, partition management) than a plain queue (shards or partitions to size, and consumer checkpointing on Kinesis and Event Hubs).
Revisit when
Per-customer alert volume becomes uneven enough that noisy tenants starve quieter ones on shared shards. That forces a partitioning or per-tenant stream decision rather than a return to queues.
Decision
Federate authentication to each enterprise customer's own identity provider instead of maintaining Sentrio-managed credentials for every user.
Why
Enterprise customers expect to provision and de-provision vendor access through their own identity system, and a security review specifically checks for this; a Sentrio-managed password store is both a worse customer experience and a larger attack surface to defend.
Alternatives considered
- Sentrio-managed usernames and passwords: workable while customers were small teams buying for themselves, and unacceptable to most enterprise security teams now.
Trade-off
Federation adds integration work per customer's identity provider quirks, and a customer's own IdP outage now affects Sentrio login too.
Revisit when
A customer's identity provider falls outside the SAML and OIDC support already built, or contracts start requiring automated user provisioning (SCIM) on top of federation.
Decision
Route analytics and dashboard queries to read replicas instead of querying the primary database directly.
Why
The ingestion pipeline now writes to the primary continuously; letting dashboard and reporting queries compete with that write load risks slowing down alert correlation during active incidents, the moments when speed matters most.
Alternatives considered
- Continuing to query a single database instance directly: adequate at low volume, a risk at Sentrio's write volume.
Trade-off
Read replicas introduce replication lag; a dashboard can be seconds behind the true current state. Acceptable for reporting, not used for anything that needs the current write.
Revisit when
Replication lag itself becomes noticeable enough to affect a customer-facing dashboard's usefulness.
Decision
Adopt a dedicated log-search and analytics engine (OpenSearch and Redshift, BigQuery, or Azure Data Explorer) instead of continuing to query the operational database directly.
Why
Log and alert volume at Sentrio's scale means scanning far more data than the operational database is built to search efficiently. Read replicas keep those scans off the writer, but they run the same engine, which is not built to scan that much data efficiently. A dedicated engine takes the workload off the operational database altogether.
Alternatives considered
- Continuing to query Aurora, Cloud SQL, or Postgres directly: the approach that stopped being adequate as ingestion volume grew.
Trade-off
A second data store to keep in sync with the source of truth, and a cost line item of its own.
Revisit when
Retention costs in the search cluster outgrow the value of keeping everything hot, which turns into a tiering decision (recent data searchable, older data archived) rather than a return to querying the operational database.
Due diligence questions
Why a managed container platform instead of Kubernetes, given you're already at 25–40 engineers?
The trigger is workload shape. Kubernetes-level scheduling control has no use in anything currently running, and each cloud's own primitives already cover the workload diversity that exists today.
How do you know one customer's alerts never leak into another customer's dashboard?
Layered enforcement, so no single check is trusted alone: tenant ID at the database row level, tenant scoping at the identity-federation layer, and tenant filtering in the log-search engine's own query layer. Enterprise customers' security reviews have tested it from the outside.
What's your recovery time objective if the primary database goes down?
With a reader or standby in a second zone, failover of a failed primary typically completes within a minute or two on all three clouds; a documented, tested recovery point and recovery time objective covers the rarer case of needing a full restore from backup, with a periodic drill to confirm that number stays true rather than becoming stale.
How do you handle a customer whose alert volume suddenly spikes 50x during an active incident?
The streaming ingestion layer (Kinesis, Pub/Sub, or Event Hubs) buffers the burst (producers retry if a throughput limit is hit, so alerts are delayed rather than lost), and the correlation-worker fleet scales out behind it, on stream lag on AWS and Azure and on push delivery on GCP; the read replicas and cache layer keep that burst from also slowing down every other customer's dashboard at the same time.
Why didn't you build your own model-evaluation pipeline?
Because the managed evaluation tooling on each cloud already answers the core question well enough, and engineering time spent building a custom harness would come directly out of time spent on the product.
What happens if an enterprise customer requires HIPAA-level guarantees you can't currently make?
It becomes a sales conversation, a compliance review, and likely a contractual and architectural change together. A service configuration alone doesn't solve it, and nobody should represent compliance posture to a customer without a qualified compliance professional involved.
How do you keep LLM inference cost from growing faster than revenue?
Model routing sends the bulk of high-volume, simple tasks to a cheaper model tier, reserving the expensive tier for complex reasoning, and cost monitoring is tied to tags so a spend spike can be traced to a specific cause rather than showing up only as a bigger total bill.
What would make you adopt Kubernetes?
A meaningful increase in workload diversity: services with resource or scheduling needs that don't fit the request-driven or event-driven models the current platforms are built around.
How do you know your model-routing layer is saving money without hurting answer quality?
The evaluation pipeline scores both tiers against the same held-out incident set, so a routing change that saves money but measurably drops task-success or groundedness scores gets caught before it ships broadly.
What's the biggest technical debt from the seed stage you're still carrying?
The tenant-isolation model is still logical, not physical, and the largest enterprise prospects are the ones most likely to eventually ask for something stronger. It hasn't been a blocker yet, and it's the item most likely to force a structural architectural change rather than an incremental one.
Architecture decisions we would revisit after Series B
- Physical, per-tenant isolation for the largest enterprise accounts, if a contract or a compliance requirement specifically demands it.
- Multi-region failover for the highest tier of customers, if an SLA requires surviving a regional outage and the cost is justified.
- Moving off the "for now" managed container platform toward Kubernetes, if workload diversity has grown enough to need it.
- Deeper compliance certifications beyond SOC 2, such as ISO 27001 or, for government-adjacent prospects, a path toward FedRAMP.
- Multi-provider LLM failover, so a single provider's outage no longer takes summarization down.
- A formal cost-governance or FinOps practice, replacing ad hoc tagging and dashboards with an owned process, once cloud spend is large enough to warrant a dedicated owner.
- An internal developer platform, once engineering headcount and service count both grow past what Terraform modules and a shared CI/CD pipeline can comfortably serve without dedicated platform tooling.