Engineering choices · Opinionated on purpose
Our technology stack, and what we refuse to use
TypeScript and Python for most new work, Java, Go and .NET where the estate or the workload calls for it, PostgreSQL as the default datastore, Terraform for infrastructure, and AWS as the primary cloud. Below is the full picture — including a table of technologies we deliberately avoid and the specific condition under which we would change our minds.
- A default stack, with a written reason required to deviate
- Chosen for your hiring pool and operating burden, not our preferences
- We work in your existing stack, including where it is not ours
- A published list of what we avoid, and what would change our view
The short answer
- Default backend
- TypeScript / NestJS or Python / FastAPI
- Default frontend
- React with Next.js, TypeScript, Tailwind
- Default datastore
- PostgreSQL
- Default cloud
- AWS, then Azure, then Google Cloud
- Default IaC
- Terraform
- Default observability
- OpenTelemetry
- Version policy
- One major behind bleeding edge; nothing pre-1.0 in production
- Enquiries
- nitesh@redcubical.com
Selection
How we choose, and why fit is only one of six criteria
How we pick a technology
Six criteria, weighed in order: fit for the real access pattern, the hiring pool available to you, the operational burden once we leave, licence and lock-in exposure, community and vendor health over five years, and our own depth. Choosing on fit alone is how organisations end up operating something excellent that nobody can hire for.
| Criterion | The question we ask | What it commonly rules out |
|---|---|---|
| Fit | Does this match the actual access pattern, data shape and consistency requirement, measured rather than assumed? | A document store chosen for a highly relational domain; a search engine used as a system of record |
| Hiring pool | Can you hire two engineers for this in your market within eight weeks, at a salary you would pay? | Elegant but niche languages and frameworks that leave you dependent on a single supplier |
| Operational burden | Who patches, upgrades and pages for this eighteen months from now, and do they exist yet? | Self-managed clusters in organisations with no platform team |
| Licence and lock-in | What does the licence permit at your scale, and what would it cost to leave in three years? | Source-available relicensing risk; managed services with no export path for your own data |
| Community and vendor health | Release cadence, issue response, commercial backing, and whether it will be maintained in five years | Single-maintainer dependencies in the critical path; frameworks whose funding model just changed |
| Our own depth | Do we have engineers who have operated this in production, not just built with it? | Anything where we would be learning at your expense without telling you so first |
The order matters. When fit and hiring pool disagree, hiring pool usually wins, because a system your team cannot staff is a system you do not really own.
Build layer
Languages, backend, frontend and mobile
Depth below is described qualitatively. "Primary" means the majority of our bench works in it daily. "Selective" means we have real production experience but would staff it deliberately rather than assume availability.
| Language | What we use it for | Our depth | Honest note |
|---|---|---|---|
| TypeScript | Web frontends, Node services, serverless handlers, CLI tooling, infrastructure in CDK where CDK is chosen | Primary | One language across the stack is a genuine team velocity advantage. It is also how a codebase ends up with types that describe hopes rather than data, so we validate at the boundary with Zod and treat any use of "any" as a review comment. |
| Python | Data engineering, machine learning, LLM orchestration, internal automation, FastAPI services | Primary | Unbeatable ecosystem for data and AI work. Packaging and runtime performance are its real weaknesses, so we pin with uv or Poetry and reach for Go when a hot path needs to be fast. |
| Java | Enterprise services, Spring Boot estates, high-throughput backends, systems with long support horizons | Deep | Verbose, and the JVM operational model needs people who understand it. Where a client already runs Java at scale, moving off it is almost never the highest-value change available. |
| Go | Network services, CLI tools, sidecars and agents, high-concurrency APIs, Kubernetes-adjacent components | Solid | Small language, fast binaries, trivial deployment. Deliberately limited, which means some abstractions are awkward to express. We do not use it for data-heavy or ML work. |
| C# and .NET | Existing .NET estates, Azure-native services, Windows-integrated line-of-business systems | Solid | Modern .NET is a genuinely good platform and cross-platform in practice. Legacy .NET Framework applications tied to Windows-only dependencies are the hard part, and that is usually why we are called. |
| Kotlin | Native Android, and Kotlin services in JVM estates that want less Java ceremony | Solid | The right answer for native Android. Server-side Kotlin is excellent but narrows your hiring pool relative to Java, which is why we ask before proposing it. |
| Swift | Native iOS where platform integration or performance rules out cross-platform | Selective | We staff native iOS deliberately rather than assuming availability. If you need both platforms native from day one, say so early so we can plan the bench. |
| SQL | Everything with a database in it: schema design, migrations, reporting, query tuning, dbt models | Primary | We treat SQL as a first-class engineering skill, not something an ORM saves you from. Review comments on query plans are normal on our teams. |
We do not list every language anyone here has used. This is what we will staff a production engagement with and stand behind at handover.
| Framework | We choose it when |
|---|---|
| NestJS (Node, TypeScript) | Default for TypeScript services. Opinionated structure and dependency injection keep a growing codebase navigable, which matters more than raw speed once a team passes about six engineers |
| Express (Node) | Small services, lambdas and internal tools where NestJS structure is overhead. Also the most common thing we inherit |
| FastAPI (Python) | Default for Python services. Async, typed, generates OpenAPI from the code, and sits naturally next to data and ML workloads |
| Django (Python) | When the admin interface, ORM and auth scaffolding genuinely save months. Strong for content and back-office systems |
| Spring Boot (Java) | Enterprise services, existing Java estates, and anywhere a long support horizon and a large hiring pool are the deciding factors |
| ASP.NET Core (C#) | Azure-centred estates and Microsoft-aligned organisations. Also the target when modernising .NET Framework applications |
| Go standard library with chi | Deliberately thin. For Go services we prefer the standard library plus a small router over a framework, because the framework rarely earns its indirection |
| Technology | We choose it when |
|---|---|
| React | Default for application UI. Largest hiring pool by a wide margin, which is usually the deciding argument rather than the technical one |
| Next.js | Server rendering, routing and content-heavy pages. Default for anything where first paint or search visibility matters |
| Vue | Where inherited. We staff and extend Vue estates competently and do not propose rewriting a working one |
| TanStack Query and Router | Server state, caching and type-safe routing. Removes most of the reason teams reach for a global state library |
| Tailwind CSS | Default styling. Fast, consistent, and keeps design decisions in one configuration file rather than scattered across stylesheets |
| Design systems | Tokenised components with Storybook and accessibility tests, once a product has more than about three surfaces to keep consistent |
| React Native | Default cross-platform mobile, especially where a web team already writes React. Native modules where the platform demands it |
| Flutter | Where the UI is highly custom and pixel consistency across platforms matters more than sharing code with the web |
| Native Kotlin and Swift | Deep platform integration, heavy background processing, tight performance budgets, or a regulated app-store requirement |
Data layer
Databases and the data platform
Which database should we use
PostgreSQL by default, because it covers relational, JSONB documents, full-text search, geospatial and vector search in one system with mature managed offerings on every cloud. Specialised stores earn their place by proving an access pattern PostgreSQL genuinely cannot serve — not by being the more interesting choice at design time.
| Datastore | Use it for | Do not use it for | Our position |
|---|---|---|---|
| PostgreSQL | Transactional systems, mixed relational and document workloads, full-text search, geospatial with PostGIS, embeddings with pgvector | Petabyte analytical scans; extreme write-throughput time series | Default. Most systems split across a relational and a document store would have been simpler, cheaper and more consistent as one PostgreSQL instance |
| MySQL | Existing MySQL and Aurora MySQL estates; simple read-heavy workloads; WordPress and similar ecosystems | Complex analytical queries; anything relying on PostgreSQL-specific features | We support it well. We would not choose it over PostgreSQL for new work, and we will not migrate a healthy MySQL estate for its own sake |
| MongoDB | Genuinely schema-variable documents, event and payload capture, rapid prototyping of an undecided model | Relational data with joins and multi-entity invariants | Used deliberately, never as a default relational substitute. The transaction and join limitations always surface later, usually in the reporting requirement nobody scoped |
| Redis | Caching, session storage, rate limiting, distributed locks, lightweight queues, leaderboards | A system of record. Anything you cannot afford to lose | Almost every system we build uses it. Nothing lives only in Redis; we set eviction policy and memory limits explicitly rather than discovering them under load |
| DynamoDB | Known, stable access patterns at very high scale; serverless architectures wanting no connection management | Ad-hoc querying; evolving access patterns; reporting | Excellent when the access pattern is settled and modelled first. Painful when it changes, because the change is a data migration rather than a new index |
| Elasticsearch and OpenSearch | Full-text relevance, faceted search, log aggregation and analytics at volume | A system of record; strongly consistent reads | We reach for PostgreSQL full-text first and move to OpenSearch when relevance tuning, faceting or scale genuinely requires it. Managed, not self-hosted, unless there is a reason |
| ClickHouse | High-volume analytical queries, product and event analytics, time-series aggregation over billions of rows | Transactional workloads; frequent single-row updates | Remarkably fast for the workload it targets, and increasingly our answer for event analytics where a full warehouse would be excessive |
The general rule: start with PostgreSQL, add a specialised store when you can describe the query it cannot serve and the volume at which that becomes a problem. Polyglot persistence is a legitimate architecture and also a common way to acquire four operational burdens instead of one.
| Component | What we use it for | Selection note |
|---|---|---|
| Snowflake | Cloud data warehouse for mixed workloads, strong governance and straightforward multi-account sharing | Compute and storage separation makes cost attribution honest. Watch warehouse auto-suspend settings; idle warehouses are the usual source of a surprise invoice |
| BigQuery | Warehouse of choice on Google Cloud, and for teams already using Google analytics data | Serverless and genuinely low-effort to start. On-demand pricing rewards good partitioning and punishes unbounded queries, so we set query cost controls on day one |
| Amazon Redshift | AWS-native warehousing where the estate is already deeply AWS and Redshift is mandated or incumbent | Serverless has removed most of the old operational pain. For greenfield work we more often propose Snowflake or a lakehouse on S3 |
| Databricks | Lakehouse architectures, large-scale Spark transformation, machine learning workloads next to the data | The right answer when data science and engineering share one platform. Overkill if what you actually needed was dbt on a warehouse |
| dbt | Transformation, testing and documentation of warehouse models; the layer where a metric becomes canonical | Non-negotiable on any warehouse we build. Tests on canonical metrics are what stop two departments arriving at a meeting with different numbers |
| Apache Airflow | Scheduled batch orchestration, especially where a managed offering exists and the team already knows it | Ubiquitous and well understood. Local development and dependency management remain its weak points |
| Dagster | Asset-oriented pipelines where lineage and data quality checks are first-class concerns | Better developer experience and a clearer model than Airflow. Smaller hiring pool, which is why we ask before choosing it |
| Apache Kafka | Event streaming, service decoupling, change data capture transport, event sourcing | Managed only unless there is a specific reason. Confluent Cloud or MSK. Self-managing Kafka is a platform-team commitment, not a configuration choice |
| Debezium | Change data capture from PostgreSQL, MySQL and SQL Server into the platform without touching application code | The cleanest way to get operational data into a warehouse without dual writes. Requires care with schema evolution and replication slot monitoring |
For most mid-sized organisations the honest first data platform is change data capture into object storage, a warehouse, dbt with tests, and one semantic layer. Streaming, a lakehouse and a feature store are additions you should be able to justify with a named use case.
Intelligence and platform
AI and machine learning, cloud services and delivery tooling
| Technology | What we use it for | Selection note |
|---|---|---|
| Amazon Bedrock | Default managed access to multiple model families on AWS estates, with data staying inside the account boundary | Model choice without a separate vendor relationship, and no training on your prompts. Our first proposal on most AWS-based AI work |
| Azure OpenAI Service | Microsoft-aligned organisations, and where enterprise agreements and regional deployment are the deciding factors | Strong compliance posture and regional control. Quota and capacity planning need attention earlier than teams expect |
| Google Vertex AI | Google Cloud estates, Gemini model access, and workloads that sit close to BigQuery | Natural choice when the data already lives in BigQuery. Weakest of the three in our own bench depth, and we say so |
| Amazon SageMaker | Custom model training, hosted inference endpoints, and pipelines for classical machine learning | Broad and correspondingly complex. We use the parts we need rather than adopting the whole platform by default |
| pgvector | Vector search where the corpus is already in PostgreSQL and volumes are moderate | First choice for retrieval-augmented generation. One database instead of two is worth a great deal operationally |
| OpenSearch vector search | Hybrid keyword and semantic retrieval where relevance tuning matters as much as similarity | The right answer when pure vector similarity is not producing usable retrieval, which is more often than the demos suggest |
| Pinecone and Qdrant | Dedicated vector databases at larger corpus sizes or where filtered search performance is the binding constraint | Chosen when pgvector has been measured and found wanting, not before. Qdrant where self-hosting or open licensing matters |
| LangGraph | Multi-step agentic workflows needing explicit state, retries and human-in-the-loop checkpoints | We prefer explicit graphs over implicit agent frameworks, because a production workflow needs to be debuggable when a step fails at 3 a.m. |
| PyTorch | Custom model training and fine-tuning where a hosted model genuinely does not fit | Used far less often than clients expect. Most business problems presented as model training are solved better by retrieval and prompt design |
| scikit-learn | Classical machine learning: churn, propensity, forecasting, anomaly detection, classification on tabular data | Still the correct answer for a large share of real business predictions. Gradient boosting on tabular data beats a neural network more often than the discourse admits |
Our standing advice on AI work: fix retrieval before reaching for a bigger model, set a cost-per-interaction budget before writing a prompt, and design model tiering on day one. That is described in detail on our AI, ML and LLM engineering page, and it came out of running Vedant.
| Capability | AWS | Azure | Google Cloud | Our default |
|---|---|---|---|---|
| Container runtime | ECS Fargate, EKS | Container Apps, AKS | Cloud Run, GKE | ECS Fargate, unless a named Kubernetes requirement exists |
| Serverless compute | Lambda | Functions | Cloud Functions, Cloud Run | Lambda for event work and spiky APIs |
| Managed relational | RDS, Aurora PostgreSQL | Azure Database for PostgreSQL | Cloud SQL, AlloyDB | Aurora PostgreSQL |
| Object storage | S3 | Blob Storage | Cloud Storage | S3 with lifecycle policies from day one |
| Managed streaming | MSK, Kinesis | Event Hubs | Pub/Sub | MSK for Kafka compatibility, Kinesis for simpler pipelines |
| Identity and access | IAM, Cognito | Entra ID, B2C | Cloud IAM, Identity Platform | Entra ID where the organisation is Microsoft-aligned, otherwise Cognito or Auth0 |
| Secrets management | Secrets Manager, Parameter Store | Key Vault | Secret Manager | Native service, never environment files in a repository |
| Managed model access | Bedrock | Azure OpenAI | Vertex AI | Bedrock on AWS estates |
| Warehouse | Redshift, Athena on S3 | Synapse, Fabric | BigQuery | Snowflake or BigQuery, chosen on the wider estate |
| Edge and CDN | CloudFront | Front Door | Cloud CDN | CloudFront, or Cloudflare where it is already in place |
We recommend a single primary cloud unless data residency or a regulatory requirement genuinely forces otherwise. Multi-cloud doubles the operational surface and rarely produces the commercial leverage it is sold on.
| Area | What we use |
|---|---|
| Infrastructure as code | Terraform and OpenTofu by default; AWS CDK for single-cloud TypeScript teams; Pulumi where infrastructure genuinely needs general-purpose code |
| Policy as code | Checkov and Open Policy Agent in the pipeline, blocking on plan rather than reporting after apply |
| CI/CD | GitHub Actions as default; GitLab CI and Azure DevOps where incumbent; Argo CD for GitOps delivery into Kubernetes |
| Artefact and supply chain | One immutable artefact promoted across environments, cosign signatures, SBOM generation on every build |
| Containers | Docker, distroless or Alpine base images, multi-stage builds, no root at runtime |
| Observability | OpenTelemetry instrumentation, Grafana and Prometheus, CloudWatch, Datadog where already licensed |
| Logging | Structured JSON with trace and span identifiers, centralised, with retention tiers set deliberately |
| Reliability | Three to five SLOs per service, burn-rate alerting, error budget policy agreed in writing before launch |
| Incident tooling | PagerDuty or Opsgenie, a runbook per alert, blameless review within five working days |
| Area | What we use |
|---|---|
| Unit and component | Vitest and Jest for TypeScript, pytest for Python, JUnit for Java, xUnit for .NET |
| API and integration | Supertest, pytest with testcontainers, RestAssured. Real dependencies in containers rather than deep mock hierarchies |
| Contract testing | Pact for consumer-driven contracts across service boundaries |
| End to end | Playwright as default. Kept to the journeys that generate revenue, because a large brittle suite gets ignored |
| Load and performance | k6 and Locust, run against production-shaped data volumes rather than a seeded fixture |
| Accessibility | axe-core in the pipeline plus manual keyboard and screen-reader passes on key journeys |
| Dependency and container scanning | Trivy, Grype, Dependabot and Renovate, with fixable criticals blocking the build |
| Static analysis and SAST | Semgrep and CodeQL, tuned to reduce noise rather than left at defaults |
| Secret scanning | gitleaks pre-commit and in the pipeline, plus history scanning on any repository we inherit |
| Dynamic and penetration testing | OWASP ZAP in the pipeline; independent penetration testing coordinated with a third party for release gates |
Tooling we work with day to day
- Terraform
- GitHub Actions
- Argo CD
- Docker
- Kubernetes
- OpenTelemetry
- Grafana
- Prometheus
- Datadog
- PagerDuty
- Playwright
- k6
- Semgrep
- Trivy
- gitleaks
- Checkov
- Open Policy Agent
- Snyk
- Renovate
- cosign
Honest limits
What we deliberately avoid, and why
Every row carries the condition under which we would change our mind. A refusal with no condition attached is dogma rather than judgement, and you should push back on any vendor who cannot supply one.
What we will not build with
We avoid technologies that shift cost onto your future team: no-code for core business logic, microservices before a modular monolith, MongoDB as a relational substitute, blockchain without a real trust boundary, pre-1.0 frameworks in production, and self-hosting what a managed service does well. Each of these has a condition that would change our answer, listed below.
| We avoid | Why | We would reconsider if |
|---|---|---|
| No-code and low-code platforms for core business logic | Your competitive logic ends up expressed in a proprietary visual format that cannot be reviewed, unit tested, diffed or migrated. Version control and debugging are weak, and pricing scales with usage rather than value. The exit cost is a full rebuild. | The use case is internal workflow, forms, approvals or a departmental tool with a short expected life. We actively recommend these platforms for exactly that, and we will tell you when your requirement is one. |
| Microservices before a modular monolith | Microservices solve an organisational problem at the price of distributed transactions, network failure modes, distributed tracing, per-service deployment and a much harder local development story. Below roughly twenty-five engineers you take the cost without the benefit. | You have multiple independent teams that genuinely need independent release cycles, or a specific component whose scaling profile is so different that it must be isolated. Then we extract that one boundary, not all of them. |
| MongoDB as a default relational substitute | Most business domains are relational. When you model them as documents, the joins move into application code, invariants stop being enforceable by the database, and the reporting requirement nobody scoped arrives in month nine and is very expensive. | The data is genuinely schema-variable, or you are capturing heterogeneous payloads and events. We will still ask whether PostgreSQL JSONB gets you the same flexibility with transactions intact. |
| Blockchain without a genuine trust-boundary problem | A distributed ledger earns its enormous complexity only when mutually distrusting parties must agree on state with no acceptable intermediary. In almost every enterprise proposal we have reviewed, that intermediary exists and is acceptable, and a signed audit log in PostgreSQL meets the actual requirement. | You can name the mutually distrusting parties, explain why no party can hold the record, and show why a cryptographically signed append-only log is insufficient. That case exists. It is rare. |
| Bleeding-edge frameworks below a version-1 release | Breaking changes between minor versions, thin documentation, no upgrade path, and a hiring pool of roughly nobody. You inherit all of that at handover, after we have left. | It is the only reasonable way to solve the problem. Then we say so explicitly, isolate it behind an interface, record the risk in an architecture decision record and agree who owns the upgrade. |
| Self-hosting what a managed service does well | Self-managed PostgreSQL, Kafka, Elasticsearch or Kubernetes control planes consume platform engineering capacity permanently. The licence saving is real and almost always smaller than the salary cost of the people patching, upgrading and paging for it. | Data residency or regulatory constraints rule out the managed option, the scale genuinely changes the economics, or you already have a platform team with the capacity and the appetite. |
| Internet Explorer support | It is out of support. Supporting it constrains your CSS, your JavaScript and your build pipeline, and forces polyfills that slow the experience for everyone else in order to serve a fraction of a percent. | You have measured analytics showing a material share of revenue arriving on it. In that case we scope a separate degraded experience rather than compromising the main one. |
| Self-managed Kafka for small teams | Broker upgrades, partition rebalancing, ZooKeeper or KRaft migration, disk pressure and consumer lag debugging are a platform-team responsibility. Teams under about fifteen engineers end up with a critical dependency nobody is confident operating. | You have a dedicated platform team, or a compliance requirement that prevents using MSK or Confluent Cloud. Otherwise managed Kafka, or often just SQS and SNS, is the better engineering answer. |
| ORMs used to avoid learning SQL | ORMs are useful for routine create, read, update and delete work. Used as a substitute for understanding SQL they produce N+1 queries, unreadable generated joins and teams who cannot read a query plan when performance degrades. | Nothing. We will keep using ORMs for the straightforward eighty percent, and we will keep writing and reviewing raw SQL for reporting, window functions and anything where the plan matters. |
| GraphQL as a default API layer | It genuinely solves over-fetching for many clients with divergent needs. It also brings query complexity limits, caching difficulty, N+1 resolver problems and authorisation logic spread across resolvers, which is a lot to hand a small team. | You have several client applications with materially different data requirements, or a public API where clients cannot be coordinated. For a single web and mobile client, a well-designed REST API is usually less total work. |
| Multi-cloud as a default posture | Two clouds means two identity models, two network models, two monitoring stacks and two sets of expertise, for negotiating leverage that in our experience does not materialise. We have run a nine-month dual-cloud overlap and it bought nothing but cost. | Data residency or regulatory requirements demand it, or a specific managed service exists on only one provider. Then we isolate that workload rather than adopting multi-cloud as an architecture. |
This list costs us work. Clients occasionally arrive having already decided on one of these and go elsewhere when we argue against it. We would rather lose that engagement than build something we would have to defend at handover.
Answers
Technology stack questions
What is Redcubical Systems' default technology stack?
TypeScript on Node with NestJS or Python with FastAPI on the server, React with Next.js on the web, React Native for cross-platform mobile, PostgreSQL as the primary datastore, Terraform for infrastructure, GitHub Actions for delivery and OpenTelemetry for observability, on AWS. That is the default we deviate from with a written reason, not a rule.
Why do you default to PostgreSQL?
Because it is a genuinely general-purpose datastore. Strong relational guarantees, JSONB when you need document flexibility, full-text search, PostGIS for geospatial, pgvector for embeddings, and mature managed offerings on every cloud. Most systems that were split across a relational database and a document store would have been simpler and cheaper as one PostgreSQL instance.
Will you work in a stack you would not have chosen?
Yes, and we do it regularly. Inherited Vue, Angular, PHP, Rails and .NET Framework estates are normal. Rewriting a working system into our preferred stack is usually the most expensive way to deliver no new business value. We will tell you where the existing choice is costing you and let you decide whether that is worth addressing now.
Should we use microservices?
Probably not yet. Microservices solve an organisational problem — independent teams deploying independently — at the price of distributed systems complexity. Under roughly twenty-five engineers you usually have the cost without the benefit. Build a modular monolith with clean internal boundaries and extract a service when a specific boundary demonstrably needs its own scaling or release cycle.
How do you decide which database or cloud service to use?
Six criteria, weighed in this order: fit for the actual access pattern, the hiring pool for the client, the operational burden after we leave, licence and lock-in exposure, community and vendor health over a five-year horizon, and our own depth. Fit alone is how teams end up operating something nobody can hire for.
Do you use ORMs?
Yes, for the eighty percent of queries that are straightforward create, read, update and delete work, where an ORM genuinely reduces boilerplate and injection risk. We do not use them to avoid understanding SQL. Anything involving reporting, window functions or a query plan that matters gets written as SQL and reviewed as SQL.
Which cloud do you recommend if we have no incumbent?
A single primary cloud, usually AWS, because our bench is deepest there and the managed service coverage is broadest. Azure where the organisation is already committed to Microsoft identity and licensing. Google Cloud where the workload is data and machine learning first. We advise against a multi-cloud posture as a default: it doubles operational surface and rarely delivers the negotiating leverage it promises.
How current do you keep your stack?
We adopt one major version behind the bleeding edge as a rule of thumb, and we do not put anything below a version-1 release into a production system a client has to own. The exception is when a pre-1.0 library is the only reasonable way to solve the problem, in which case we say so, isolate it behind an interface and record the risk.
Have an architecture decision to make
Bring the choice you are weighing to a technical call. You will speak to an architect who has operated these systems in production, and you will get a recommendation with its trade-offs named rather than a capability list.