This page describes the runtime infrastructure that the rest of the Architecture section assumes. It sits alongside System overview, Application architecture, Backend, Integrations, and Security and operations, and it answers the practical question those pages leave open: where the API process, the worker loop, the database, the search index, the object store, the cache, the queue, the edge, and the observability stack actually run, and how a build moves from a developer's machine into the hands of public-beta users. The platform separates four execution layers — local developer machines, a deployed Dev environment, a Test and Staging release gate, and Production — and gives each one a distinct purpose, a distinct provider posture, and a distinct deployment trigger. Application compute runs on Hetzner Cloud and is orchestrated by K3s in the three deployed environments; MongoDB Atlas backs Test, Staging, and Production with self-managed MongoDB Community plus mongot reserved for Dev; Hetzner Object Storage holds uploaded models, generated assets, export artifacts, and backup payloads; Cloudflare provides DNS, edge Transport Layer Security, content delivery, Web Application Firewall coverage, and traffic shaping; Redis accelerates cache, locks, idempotency windows, rate-limit counters, and queue work; and a Prometheus, Grafana, Loki, Tempo, Alertmanager, and OpenTelemetry stack covers metrics, logs, traces, and alerting. The infrastructure is intentionally small but it is not a toy: Phase A must support the public Web and Progressive Web App beta, real preorder intent, user uploads up to one hundred megabytes, asynchronous model-processing jobs, language-model translation workflows, telemetry, customer support, rollback, backup and restore, and a credible path to native iOS and Android targets when those phases open.
DomiDo is not a simple create-read-update-delete application, so the infrastructure has to satisfy five distinct workload classes at the same time. Web and Progressive Web App static delivery puts pressure on content-delivery bandwidth and cache correctness: the Expo Web bundle, images, the application shell, and public gallery media must be served with long cache time-to-live for immutable assets and a short time-to-live for application configuration. Interactive API traffic — authentication, projects, designs, preorder intent, designer discovery, support, and administration — is bounded by Central Processing Unit, MongoDB latency, Redis cache hit rate, and the ninety-fifth-percentile response time, and it must run on horizontally scalable stateless API pods. The upload and media validation class — three-dimensional model uploads, previews, thumbnails, and generated images — pushes object storage and worker CPU and memory, and it relies on direct-to-object-storage upload with asynchronous validation and strict declared limits. Heavy model processing — model parsing, voxelisation, block-kit generation, and geometry simplification — needs a dedicated heavy-worker node pool with concurrency caps, timeout, and retry policy because it cannot be allowed to starve interactive API traffic. Provider-driven asynchronous jobs — language-model translation, AI tools, email and support delivery, analytics exports, and payment webhooks — depend on external latency and a retry budget, and they run inside queues that carry idempotency keys, provider circuit breakers, and dead-letter handling.
The current domido/app implementation is an Expo and React Native application that targets React Native Web as the present Web and Progressive Web App surface. The runtime is Expo at the ~54.0.33 line, React Native at 0.81.5, React Native Web at ~0.21.0, and Expo Router at ~6.0.23; build scripts cover expo export -p web, expo start --web, expo start --ios, and expo start --android. Static assets currently weigh about forty-seven megabytes across assets and public, application source is about five point three megabytes under src, and the asset, public, and source footprint is around one hundred and sixty-eight files. The practical consequence for infrastructure is that the Web and Progressive Web App build must be treated as one target of a universal application — not a separate web-only architecture — and that content-delivery caching plus content hashing matter even before user-generated media grows.
The starting capacity assumptions below are deliberately explicit so they can be replaced with measured production data once beta traffic begins. Every monetary description is a qualitative posture rather than a precise figure; the infrastructure is sized for a tight startup-grade budget appropriate for a public beta, excluding variable AI-provider and payment-provider fees.
| Area | Phase A beta assumption | Why it matters |
|---|---|---|
| Monthly active users | 10,000 MAU | Founder-led acquisition plus public beta marketing can create sharp spikes. |
| Daily active users | 1,000 DAU | Used for API, cache, support, and telemetry sizing. |
| Peak concurrent users | 100-200 | Used for API replica, ingress, and Web and Progressive Web App asset delivery sizing. |
| Normal API load after content-delivery network | 10-30 RPS sustained | Most browsing should be cached at edge or served with short-lived API cache. |
| Short burst API load | 100-150 RPS | Must survive social, demo, or newsletter bursts. |
| Upload max size | 100 MB per user model file | Matches requirements for GLB, GLTF, OBJ, and STL uploads. |
| Heavy model jobs | 1 concurrent job initially, 2 after first scaling trigger | Voxelisation and block-kit generation must not starve API traffic. |
| Light background jobs | 4-8 concurrent jobs | Translation, publication, email, analytics, cleanup, and provider calls. |
| Initial object storage | 500 GB allowance planning target | Uploaded models and generated previews can grow faster than database data. |
| Beta reliability goal | practical 99.5% availability | Good enough for beta while avoiding overbuilding. |
| Business data Recovery Point Objective | 15 minutes or better in production | Mirrors existing reliability requirements. |
| Object asset Recovery Point Objective | 24 hours or better initially | Large assets are less transactional than business data. |
| Monthly infrastructure budget | startup-grade, small monthly spend | Excludes variable AI, Stripe, email, and support-provider spend. |
The five workload classes themselves carry the following baseline handling rules:
| Workload | Examples | Primary resource pressure | Required handling |
|---|---|---|---|
| Web/PWA static delivery | Expo Web bundle, images, application shell, public gallery media | content-delivery bandwidth, cache correctness | Serve immutable assets with long cache time-to-live; keep application configuration short-lived. |
| Interactive API | auth, projects, designs, preorder intent, designer discovery, support, admin | CPU, MongoDB latency, Redis cache, p95 response time | Horizontally scalable stateless API pods. |
| Upload and media validation | 3D model uploads, previews, thumbnails, generated images | object storage, antivirus and format validation, worker CPU and memory | Direct-to-object-storage upload, async validation, strict limits. |
| Heavy model processing | model parsing, voxelisation, block-kit generation, geometry simplification | CPU, memory, temporary disk | Dedicated heavy-worker node pool, concurrency caps, timeout and retry policy. |
| Provider-driven async jobs | LLM translation, AI tools, email, analytics exports, payment webhooks | external latency, retry budget, cost control | Queue jobs, idempotency keys, provider circuit breakers, dead letters. |
The platform separates local development from deployed environments so that a local Docker setup is never mistaken for Dev and deployment problems are never discovered for the first time in Staging. Local is the fast deterministic coding loop that runs unit and integration tests against Docker Compose services and fake providers before merge; nothing about local execution counts as deployment evidence. Dev is the first real deployed developer environment — it runs on a single-node K3s cluster in the domido-dev Hetzner project against a separate self-managed MongoDB Community plus mongot node, it auto-deploys from main after Continuous Integration checks pass, and it carries synthetic developer accounts that are resettable at any time; Dev is allowed to be unstable, and it is not a public beta environment. Test and Staging is the stable release-candidate gate that proves a specific version is production-ready: it runs on a single-node K3s cluster in the domido-test Hetzner project against MongoDB Atlas Staging starting at the M10 tier, it accepts only release-candidate tags or protected release branches as deployment triggers, and it must remain stable long enough for release gates to run end to end. Production is the public beta runtime: it runs the high-availability K3s baseline in the domido-prod Hetzner project against MongoDB Atlas Production starting at M20, it deploys only by manual approval after Staging gates pass, and it holds real user, support, telemetry, and preorder-intent data behind production keys, budgets, alerts, kill switches, and a documented rollback path.
The diagram traces a build from the developer's machine through the merge request, the Continuous Integration pipeline, and the container registry, and then forks: every successful build of main flows automatically into Dev, while only a tagged release candidate flows into Test and Staging; Production is reached only after the Test gates pass and a human approves the promotion.
The environments differ on every axis that matters for safety. Application compute is a per-environment Hetzner project; the database moves from a local Docker MongoDB, through a self-managed MongoDB Community single-node replica set on the Dev database node, to MongoDB Atlas Staging, to MongoDB Atlas Production. Vector search follows the same path: fake embeddings or local index tests in development, self-managed mongot in Dev, and Atlas Vector Search in both Test/Staging and Production. Object storage moves from a local MinIO emulator to real isolated Hetzner buckets for Dev, Test, and Production. Secrets stay environment-scoped: local .env files that never reach Git, Dev-only secrets, Test-provider secrets, and Production-provider secrets, with no reuse across boundaries. Data progresses from generated fixtures to synthetic resettable developer data to synthetic or sanitised release data to real user data. Telemetry has its own workspace per environment. Rollback is not applicable locally, best-effort in Dev, required as smoke evidence in Test, and required as a tested path in Production.
| Layer | Purpose | Runtime | Data | Provider policy | Deploy trigger |
|---|---|---|---|---|---|
| Local | Fast deterministic coding and automated tests before merge. | Developer machine with local Docker Compose services. | Generated fixtures only. | Fake providers by default; real provider calls only through explicit developer-run tests. | Developer command. |
| Dev | First deployed developer environment; proves merged code works as deployed. | Hetzner domido-dev, single-node K3s plus separate dev DB/search node. |
Synthetic developer test accounts, resettable. | Real non-production or sandbox providers where available; LLM dev project with strict budget cap. | Automatic from main after CI passes. |
| Test/Staging | Stable release-candidate gate; proves a specific version is production-ready. | Hetzner domido-test, single-node K3s plus Atlas Staging. |
Synthetic or sanitised release-validation data. | Sandbox or test provider projects only. | Release candidate tag or protected release branch. |
| Production | Public beta runtime for real users and real preorder intent. | Hetzner domido-prod, HA K3s baseline plus Atlas Production. |
Real user, support, telemetry, and preorder-intent data. | Live providers with budgets, alerts, kill switches, and rollback plan. | Manual approval after staging gates pass. |
Provider verification is intentionally graded by environment so that Dev and Test are real integration evidence rather than mocks. Locally, the language-model provider is a fake by default, object storage is a MinIO emulator, payments are a faked or mocked Stripe client, and email and support write to a fake sink — enough to test application logic, error handling, idempotency, retries, and job state without spending real money or producing real provider effects. Dev moves to real development or sandbox providers with a strict daily budget cap, Hetzner Dev buckets, Stripe test mode when payment or preorder work is active, and a sandbox inbox, which proves that deployed workloads can reach real non-production providers with real credentials and real network egress. Test and Staging uses sandbox or test provider projects with full webhook signature verification, which provides release-candidate integration evidence. Production uses live provider keys with a kill switch, budget alerts, and a documented fallback. The contract is that fake providers are necessary for speed but they are never deployment evidence: Dev and Test must use real non-production integrations for any smoke path where the provider supports them.
The local developer stack itself runs a small fixed set of services: local-mongodb as a single-node replica set for repositories, transactions, jobs, idempotency, and outbox tests; local-redis for cache, rate-limit counters, locks, and queue acceleration tests; local-object-storage as a MinIO or S3-compatible emulator for presigned upload and download and object metadata tests; fake-llm-provider, fake-email-support, and fake-payment-webhook to produce deterministic responses, controlled error and timeout modes, and signed test webhook payloads; and local-otel-sink to capture logs, metrics, and traces locally or to write them to standard output for automated assertions.
The topology is laid out from the edge inward. Web and Progressive Web App users reach the platform through Cloudflare, which terminates Transport Layer Security at the edge and provides Domain Name System, content delivery, Web Application Firewall coverage, and rate limiting before any traffic touches origin. Cloudflare hands HTTPS to a Hetzner LB11 load balancer in front of the production K3s cluster, which is divided into a three-node control plane on the CPX22 instance type, two application-worker nodes on CPX32 carrying the API, the web static service, and light workers, one heavy-worker node on CCX23 for model jobs and voxelisation, and one observability node on CPX22 that hosts Prometheus, Grafana, Loki, and Tempo. Redis runs inside the cluster as an accelerator next to the application workers. The application reaches sideways into MongoDB Atlas for both the operational cluster and Atlas Search and Vector Search, and into Hetzner Object Storage for uploads, generated assets, and backup payloads. External providers — language-model and AI tools, the email and support provider, Stripe in test or live mode depending on phase, and the customer analytics provider — are called from the application workers and, in the case of heavy jobs touching the database, Redis, or object storage, from the heavy-worker node.
Hetzner instance availability and gross pricing were verified through the live Hetzner Cloud API on 2026-05-14, and final provisioning must always re-check availability immediately before creation because cloud capacity changes. The baseline uses currently available CPX and CCX server types in the checked EU datacentres. The CPX22 instance — two shared x86 vCPU, four gigabytes of memory, eighty gigabytes of disk — carries the K3s control plane, the observability node, and small deployed utility nodes. The CPX32 instance — four shared x86 vCPU, eight gigabytes of memory, one hundred and sixty gigabytes of disk — carries the application workers, the Dev database node, and the Test K3s node. The CPX42 instance — eight shared x86 vCPU, sixteen gigabytes of memory, three hundred and twenty gigabytes of disk — is the application-worker resize target and the non-production database resize target. The CCX23 instance — four dedicated x86 vCPU, sixteen gigabytes of memory, one hundred and sixty gigabytes of disk — is the dedicated heavy-worker baseline and the production hot-path upgrade target. The LB11 load balancer is the production ingress front door.
| Server type | Recommended use | CPU | RAM | Disk | Deprecated | Checked EU availability |
|---|---|---|---|---|---|---|
CPX22 |
K3s control plane, observability, small deployed utility node | 2 shared x86 vCPU | 4 GB | 80 GB | false | fsn1, hel1, nbg1 |
CPX32 |
App workers, Dev DB, Test cluster | 4 shared x86 vCPU | 8 GB | 160 GB | false | fsn1, hel1, nbg1 |
CPX42 |
App worker resize target, non-prod DB resize | 8 shared x86 vCPU | 16 GB | 320 GB | false | fsn1, hel1, nbg1 |
CCX23 |
Dedicated heavy-worker CPU and production hot-path upgrade | 4 dedicated x86 vCPU | 16 GB | 160 GB | false | fsn1, hel1, nbg1 |
LB11 |
Production ingress load balancer | shared load balancer | n/a | n/a | false | EU locations |
The CX33 line is not selected for the baseline because availability in the checked EU datacentres was limited at the time of the last check. The preferred location order is hel1, then nbg1, then fsn1, and one location per environment is used unless a real availability issue forces otherwise. A small K3s cluster is not split across regions during Phase A: cross-region latency and operational complexity outweigh the resilience benefit at beta scale.
The Dev deployed environment lives in the domido-dev Hetzner project on a private network at the suggested classless inter-domain routing block 10.20.0.0/16. K3s runs single-node on domido-dev-k3s-01, a CPX32; the database and search node domido-dev-db-01 is a separate CPX32 running self-managed MongoDB Community as a single-node replica set plus mongot. Object storage uses real Hetzner buckets in the domido-dev-* namespace; public hostnames are dev.domido.example and api-dev.domido.example. Providers run in real non-production or sandbox accounts where available, with a strict daily budget cap on the language-model project. Data is synthetic and resettable, availability is best-effort, and deployment is automatic from main after Continuous Integration passes. The Dev K3s node carries the API, the web and Progressive Web App static service, light workers, one capped heavy worker, and a reduced-retention Prometheus, Grafana, Loki, and Tempo stack; MongoDB and mongot run on the separate database node so that model-processing or Kubernetes restarts cannot starve them and so the application is forced to reach its dependencies over the network rather than relying on hidden localhost assumptions. Dev limits hold uploads to one hundred megabytes, heavy-worker concurrency to one, API replicas to one or two, light-worker replicas to one or two, log retention to three to seven days, metric retention to seven days, and the language-model spend to a hard daily cap configured in the provider project and the backend environment.
Dev is responsible for validating container-runtime correctness, Kubernetes manifest correctness, environment and secret wiring, ingress and routing through /api/*, health, and admin paths, the /health, /livez, and /readyz probes, service discovery to Redis, MongoDB, object storage, and telemetry, the worker runtime under Kubernetes resource limits, provider connectivity to sandbox or development integrations, observability flow including request and job identifiers from deployed pods, and the Continuous Integration and Continuous Deployment loop from main through versioned images into the Dev cluster. Dev is not responsible for proving high availability, production Atlas behaviour, production scale, the production Service Level Objective, or legal and payment readiness — those are proven respectively by the production baseline, Test and Staging plus Production Atlas clusters, load smoke plus staging gates plus production telemetry, production monitoring and incident response, and the phase-gated Test and Staging and Production release gates. The Dev acceptance checklist requires that a merge to main builds images and deploys, that health probes pass through ingress, that the API reaches MongoDB, Redis, object storage, and telemetry from deployed pods, that one light job and one capped heavy-model job move through queued, running, and terminal states, that one sandbox language-model smoke call succeeds from a deployed worker or records a controlled provider-unavailable state, and that logs, metrics, traces, request identifier, and job identifier appear in the Dev observability workspace.
The Test and Staging environment lives in the domido-test Hetzner project on 10.30.0.0/16. K3s runs single-node on domido-test-k3s-01, a CPX32; the database is MongoDB Atlas Staging starting at the M10 tier; search uses Atlas Search and Atlas Vector Search; object storage uses the domido-test-* bucket set or a strict test prefix; hostnames are test.domido.example and api-test.domido.example. Providers run in sandbox or test projects, data is synthetic or sanitised, availability targets release-gate availability rather than a public Service Level Agreement, and deployment is triggered only by release-candidate tag or by a protected release branch — Test and Staging does not auto-deploy every merge to main, because it must stay stable long enough to prove that a specific release candidate can become production. The validation gates Test must clear cover desktop and mobile-width Web and Progressive Web App smoke, the auth, catalogue, project, upload registration, job polling, support, and administration API smoke paths, at least one model-processing job and one language-model translation job moving through the asynchronous lifecycle, direct object-storage upload and validation and signed read and cleanup and lifecycle rules, the sandbox provider smoke paths for language model, Stripe test, email and support, and object storage where the phase uses them, Atlas Search text and vector queries against expected fixtures, the security tests for rate limits, request sizes, authentication, role-based access control, and webhook signatures, observability flow including dashboards, logs, metrics, traces, and the ability of critical alerts to fire, a staging backup-restore drill within the release window, and a tested rollback to the previous image.
Production lives in the domido-prod Hetzner project on 10.40.0.0/16. The K3s control plane is three CPX22 nodes; application workers are two CPX32 nodes; the heavy worker is one CCX23 node; the observability worker is one CPX22 node; ingress is one LB11 fronted by Cloudflare; the database is MongoDB Atlas Production starting at the M20 tier; search uses Atlas Search and Atlas Vector Search; object storage uses production buckets with lifecycle, versioning where practical, and backup manifests; hostnames are domido.example, app.domido.example, api.domido.example, and admin.domido.example if needed; providers run on production keys at least privilege; data is real user, preorder-intent, support, and telemetry data; the availability target is the practical beta target of ninety-nine point five percent. Production does not run public beta on a single all-in-one node — even at the initial small size, the cluster separates control plane, user-facing application work, heavy model work, and observability.
K3s is selected for Dev, Test and Staging, and Production because the project needs repeatable deployment, workload isolation, resource limits, health probes, rolling updates, and a clean path from Web and Progressive Web App beta into native-application backend growth. Local developer machines do not run K3s; Docker Compose remains the local stack. Dev runs single-node K3s on domido-dev-k3s-01 to validate deployed runtime mechanics immediately after merge, never to host high-availability, production scale, production data, or release approval. Test and Staging runs single-node K3s on domido-test-k3s-01 to validate release-candidate behaviour against Atlas Staging and sandbox providers, not to handle daily development churn or production traffic. Production runs the high-availability K3s baseline — three control-plane nodes, two application workers, one heavy worker, and one observability worker — to run public beta with workload separation and rollback control, scaled by measured triggers rather than by intuition. Starting with Docker Compose for deployed environments and migrating later would create a second infrastructure project mid-beta, which is why Compose stays bound to local development.
The production cluster diagram shows four logical node pools that share a single etcd quorum across the three control-plane CPX22 nodes. Application worker nodes register against the control plane to pick up the API, the web static service, light workers, the scheduler, and Redis. The heavy worker node is tainted to accept only voxelisation, model parsing, and block-kit generation. The observability node is tainted to accept only Prometheus, Grafana, Loki, and Alertmanager. The three control-plane nodes are connected in pairs so that any single control-plane node can fail without losing the quorum.
| Node pool | Labels | Taints | Workloads |
|---|---|---|---|
| Control plane | node-role.kubernetes.io/control-plane=true |
control-plane taint | K3s API, etcd, system components only |
| App workers | workload=app |
none | API, web static service, light workers, scheduler, Redis |
| Heavy workers | workload=heavy |
workload=heavy:NoSchedule |
voxelization, model parsing, block-kit generation |
| Observability | workload=observability |
workload=observability:NoSchedule |
Prometheus, Grafana, Loki, Alertmanager |
Five namespaces partition workloads inside each cluster. domido-app carries the API, the web service, the workers, and the scheduler. domido-jobs carries heavier worker deployments and job-specific CronJobs when they are separated. domido-observability carries metrics, logs, dashboards, and alerts. domido-ingress carries the ingress controller and certificate automation. domido-system carries sealed and external secrets, backup jobs, and cluster utilities.
Baseline pod sizing starts from the values below and is tuned from real telemetry once beta begins. The API runs with two replicas, requests of two hundred and fifty millicores of CPU and five hundred and twelve mebibytes of memory, and limits of one CPU core and one gibibyte of memory, with the Horizontal Pod Autoscaler raising replicas up to six on CPU, latency, and queue pressure. The web and Progressive Web App static service runs two replicas at one hundred millicores and one hundred and twenty-eight mebibytes with limits of five hundred millicores and two hundred and fifty-six mebibytes, scaling to four replicas; Cloudflare is expected to absorb most static traffic. Light workers start at two replicas with five hundred millicores and five hundred and twelve mebibytes, limits of one CPU core and one gibibyte, scaling to eight by queue age and pending job count. The heavy model worker runs a single replica at two CPU cores and four gibibytes, limits of four CPU cores and ten gibibytes, capped at one replica initially and increased to two only after additional heavy capacity is added. The scheduler runs a single active instance behind a leader lock. Redis runs as a single replica on a persistent volume but is never the source of truth. Prometheus and Loki each run a single replica sized to fit the observability node with retention and ingestion tuned to match.
| Workload | Replicas | Request | Limit | Scaling rule |
|---|---|---|---|---|
| API | 2 | 250m CPU, 512 MiB RAM | 1 CPU, 1 GiB RAM | HPA to 6 replicas by CPU, latency, and queue pressure. |
| Web/PWA static service | 2 | 100m CPU, 128 MiB RAM | 500m CPU, 256 MiB RAM | HPA to 4 replicas; Cloudflare should absorb most static traffic. |
| Light workers | 2 | 500m CPU, 512 MiB RAM | 1 CPU, 1 GiB RAM | Scale to 8 by queue age and pending job count. |
| Heavy model worker | 1 | 2 CPU, 4 GiB RAM | 4 CPU, 10 GiB RAM | Max 1 initially; scale to 2 only after adding heavy capacity. |
| Scheduler | 1 | 100m CPU, 128 MiB RAM | 500m CPU, 256 MiB RAM | Single active instance with leader lock. |
| Redis | 1 | 500m CPU, 512 MiB RAM | 1 CPU, 1 GiB RAM | Persistent volume; not a source of truth. |
| Prometheus | 1 | 500m CPU, 1 GiB RAM | 2 CPU, 3 GiB RAM | Retention and scrape interval tuned to fit node. |
| Loki | 1 | 500m CPU, 1 GiB RAM | 2 CPU, 3 GiB RAM | Retention and ingestion limits required. |
Autoscaling uses the Kubernetes Horizontal Pod Autoscaler for the API and the web workload and queue-aware scaling for the workers — either KEDA or a small internal scaler once queue metrics are stable. API CPU above sixty-five percent for ten minutes adds API replicas up to node capacity; API ninety-fifth-percentile latency above eight hundred milliseconds for ten minutes adds replicas or triggers a MongoDB or cache investigation. Light-queue age above two minutes adds light-worker replicas; heavy-queue age above thirty minutes triggers a concurrency, node-capacity, and cost-guardrail review. Heavy-worker memory above eighty percent reduces concurrency or upgrades the heavy node, and Redis memory above seventy percent reduces time-to-live values, inspects key growth, and resizes before eviction affects the user experience.
Public entry runs through Cloudflare for authoritative Domain Name System, content delivery for Web and Progressive Web App static assets and safe public generated media, and Web Application Firewall coverage — Cloudflare Pro for production public beta and Cloudflare Free for Dev and Test. A Hetzner LB11 load balancer sits in front of production ingress; Transport Layer Security is terminated at the Cloudflare edge with origin Transport Layer Security to ingress. The ingress controller is Traefik, applied through K3s-compatible Helm values that are standardised across Dev, Test and Staging, and Production. Certificates are issued by cert-manager using Let's Encrypt over the Domain Name System ACME challenge through Cloudflare so the platform can rotate origin certificates without exposing public HTTP-01 challenge ports.
Firewall rules deny everything that is not explicitly required. The Internet reaches the load balancer and the ingress only over HTTPS, and the origin should reject non-Cloudflare source addresses where practical. Team addresses and Virtual Private Network endpoints reach the bastion and administration surfaces over Secure Shell and administration HTTPS, with a strong preference for Tailscale or another Virtual Private Network rather than broad Secure Shell exposure. K3s nodes talk to other K3s nodes on the required K3s ports over the private network only. Application pods reach Atlas over the Transport Layer Security MongoDB driver — and the Atlas network access list is restricted accordingly — and they reach object storage over the S3 HTTPS interface with least-privilege credentials per environment. Application pods reach external providers over HTTPS, with egress observability required. The public Internet has no access to MongoDB, Redis, or the K3s application programming interface, and there are no exceptions for production.
| Source | Destination | Allow | Notes |
|---|---|---|---|
| Internet via Cloudflare | LB / ingress | HTTPS only | Origin should reject non-Cloudflare source IPs where practical. |
| Team IPs / VPN | bastion or admin access | SSH and admin HTTPS | Prefer VPN or Tailscale; no broad SSH exposure. |
| K3s nodes | K3s nodes | required K3s ports | Private network only. |
| App pods | Atlas | TLS MongoDB driver | Atlas network access list must be restricted. |
| App pods | Object Storage | S3 HTTPS | Least-privilege credentials per environment. |
| App pods | external providers | HTTPS | Egress observability required. |
| Public internet | MongoDB, Redis, K3s API | denied | No exceptions for production. |
Public hostnames follow the same per-environment pattern: Development on dev.domido.example, api-dev.domido.example, and an optional ops-dev.domido.example; Test on test.domido.example, api-test.domido.example, and optional ops-test.domido.example; Production on app.domido.example, api.domido.example, and optional admin.domido.example, with domido.example replaced by the real domain during provisioning.
Hetzner Object Storage is the primary S3-compatible object store for Phase A. It is closer to the Hetzner application cluster than alternative providers, and it speaks the standard S3-compatible Software Development Kit patterns. Object storage is the source of truth for large binary assets — uploaded models, generated thumbnails and previews, designer media, export artifacts, Web and Progressive Web App immutable build assets when they are not served directly by the content-delivery network, and the backup payloads that hold K3s snapshots and backup manifests. MongoDB stores metadata, state, permissions, and references, never the large binary payload itself. The bucket catalogue divides storage by environment and purpose:
| Bucket | Environment | Content | Public access |
|---|---|---|---|
domido-dev-uploads |
dev | temporary model uploads and generated dev assets | private |
domido-test-uploads |
test | release-candidate upload validation assets | private |
domido-prod-uploads |
prod | original user-uploaded models and source files | private |
domido-prod-generated |
prod | generated thumbnails, previews, designer media, export artifacts | mostly private, selected signed or public CDN paths |
domido-prod-static |
prod | Web/PWA immutable build assets if not served directly by CDN deploy | public via CDN only |
domido-prod-backups |
prod | K3s snapshots, backup manifests, export bundles | private and restricted |
The upload sequence shows that the API never proxies a one-hundred-megabyte file through its pods. The client requests an upload session, the API records a pending upload, the API issues a presigned upload URL, the client uploads the file directly to object storage, the client tells the API the upload is complete, the API verifies the object metadata and size and marks the upload received, the API enqueues the validation or processing job, and the worker reads the uploaded object, runs validation or processing, and stores the result back in MongoDB. Presigned upload URLs expire in ten to fifteen minutes; downloads use signed URLs for private assets, and the content-delivery network is used only for safe public or generated assets. Object keys carry the environment, the tenant or user scope, the content type, a date partition, and an immutable object identifier. Validation covers extension, Multipurpose Internet Mail Extensions sniffing, size, parser safety, and metadata before any asset becomes usable; a malware scanner hook runs before public exposure, with format validation acting as the baseline before the scanner is fully integrated. Lifecycle rules delete abandoned pending uploads, expire old temporary files, and retain production source files unless user deletion or policy requires removal. Cross-Origin Resource Sharing is restricted to expected application origins per environment.
The database and vector-search posture is graded by environment. Dev runs self-managed MongoDB Community plus mongot on Hetzner with best-effort search, which is not a production architecture — it exists only to reduce early spend and to let developers exercise vector flows before Atlas Staging is required. Test and Staging runs MongoDB Atlas at the M10 tier with Atlas Search and Atlas Vector Search to produce production-like release evidence. Production runs MongoDB Atlas at the M20 baseline tier with Atlas Search and Atlas Vector Search for managed backups, monitoring, search, and operational support. The Test and Staging tier is upgraded when test data, index size, or smoke runs become too slow to represent production behaviour; Production is upgraded when sustained CPU rises above sixty percent, memory pressure appears, ninety-fifth-percentile read or write latency crosses target, or search and vector ninety-fifth-percentile latency crosses target during beta. The bundled Atlas Search and Vector Search compute is replaced with dedicated Search Nodes — or a higher Atlas tier — when index memory, search CPU, or query latency crosses threshold.
| Environment | Database | Search/vector | Reason |
|---|---|---|---|
| Dev | Self-managed MongoDB Community plus mongot on Hetzner |
self-managed, best effort | Low-cost deployed API, job, index, and vector-query flow validation. |
| Test / staging | MongoDB Atlas M10 | Atlas Search / Vector Search | Production-like release evidence. |
| Production | MongoDB Atlas M20 baseline | Atlas Search / Vector Search | Managed backups, monitoring, search, and operational support. |
Query and index discipline is enforced uniformly. Every user-facing list defines an explicit sort, filter, and pagination index; every search endpoint defines its expected index, fallback behaviour, and ninety-fifth-percentile target; every vector query defines its embedding model, dimension, index name, filter fields, top-k, and timeout; translated content stores the source input, context, target-language translations, status, provider metadata, and review state; jobs store status, attempts, lease, idempotency key, progress, error class, and result references; and large assets remain object-storage references rather than embedded MongoDB documents.
The backup and restore targets are explicit and measurable. Production MongoDB business data has a Recovery Point Objective of fifteen minutes or better and an initial Recovery Time Objective of four hours, served by Atlas continuous backup or scheduled snapshots plus restore drills. Test MongoDB has a Recovery Point Objective of twenty-four hours and a one-business-day Recovery Time Objective via Atlas snapshot or fixture rebuild. Dev MongoDB runs best-effort with a snapshot before destructive Dev environment changes. Production object assets have a twenty-four-hour Recovery Point Objective and an eight-hour Recovery Time Objective via object-storage lifecycle and versioning plus inventory manifests. K3s cluster state has a six-hour Recovery Point Objective and a four-hour Recovery Time Objective via encrypted etcd snapshots to the backup bucket.
| Data | RPO | RTO | Mechanism |
|---|---|---|---|
| Production MongoDB business data | 15 minutes or better | 4 hours initial beta target | Atlas continuous backup or scheduled snapshots plus restore drill. |
| Test MongoDB | 24 hours | 1 business day | Atlas snapshot or fixture rebuild. |
| Dev MongoDB | best effort | best effort | snapshot before destructive dev environment changes. |
| Production object assets | 24 hours | 8 hours initial beta target | Object storage lifecycle/versioning where practical plus inventory manifests. |
| K3s cluster state | 6 hours | 4 hours | encrypted etcd snapshots to backup bucket. |
Redis is an accelerator, not the source of truth. MongoDB stays authoritative for business state and job state. Redis carries short-lived application-programming-interface cache entries for public and catalogue reads and repeated lookup data; per-Internet-Protocol-address, per-user, per-session, and per-endpoint rate-limit counters; fast lookup for recent idempotency keys backed by durable MongoDB records; queue visibility, lease hints, and worker coordination where work is not fully MongoDB-backed; short-lived distributed locks for the scheduler and webhook deduplication; and optional session helpers — though the authentication source of truth remains durable. Cache time-to-live defaults follow the same logic: one year for immutable Web and Progressive Web App assets that carry content-hashed filenames, thirty to sixty seconds for the application-shell configuration so feature-flag and maintenance changes propagate quickly, thirty to one hundred and twenty seconds for public catalogue lists, sixty to three hundred seconds for design and detail public metadata with explicit invalidation on publication changes, five minutes for designer-profile snippets with invalidation on profile update, two to five seconds for client-side job-status polling rather than heavy server-side cache, five to fifteen minutes for signed media URLs that must not be cached broadly, and one minute to twenty-four hours for rate-limit counters depending on endpoint and abuse pattern.
Queue strategy treats MongoDB-backed queues as the simple-first option for the backend specification, but exposes queue metrics so Redis or KEDA acceleration can take over without rewriting business flows. Translation and localisation runs four to eight concurrent jobs with exponential-backoff retry on transient provider failures and dead-letter handling on permanent failures. Model validation runs one to two concurrent jobs and retries infrastructure failures but never retries unsafe or malformed input. Voxelisation and block-kit generation runs one concurrent job initially under strict timeout, with progress updates and manual retry on expensive failure. Publication and cache invalidation runs two to four concurrent jobs with retry to success within a bounded window. Email and support notifications run two to four concurrent jobs with provider retry and idempotency keys. Analytics export runs one or two concurrent jobs at low priority and is allowed to lag.
Long-running tasks must never block interactive application-programming-interface requests, and every long task uses a job resource, a progress model, a timeout, a cancellation path, and an idempotency key.
The job state machine moves from queued through leased to running, branches into succeeded, retry-wait, failed, or cancelled, and returns expired leases to the queue when a worker fails to renew them. Workers renew their lease while running, every job type has a maximum runtime, user or administrator cancellation marks intent and workers check for it at safe points, progress is stored as percentage or stage plus a human-readable state for the user interface, duplicate job-start requests return the existing job when safe, AI and heavy model jobs carry daily, per-user, and per-environment budgets, permanent or exhausted failures land in a dead-letter view that operations and administration can see, and the platform emits queue age, runtime, attempts, failure class, provider latency, and cost estimate as observable signals.
The backend repository uses GitLab delivery discipline, and the infrastructure aligns with that posture unless the project deliberately migrates later. The pipeline runs through local pre-merge checks, the merge request, the Continuous Integration suite, image production, automatic Dev deployment, release-candidate tagging, Test and Staging deployment, the release gates, a manually approved production deployment, and a post-deploy monitoring window, with a rollback path that any failed gate or critical regression can trigger.
The diagram makes the split explicit: local checks plus merge-request Continuous Integration produce versioned images, every image flows automatically into Dev, but only an image promoted to a release-candidate tag flows into Test and Staging; gates either approve a manual production deployment with a monitoring window, or they trigger rollback, and a critical regression in the monitoring window can also fall back to the previous image.
The required pipeline stages cover local pre-merge deterministic unit and integration tests against the local MongoDB, Redis, object-storage emulator, and fake-provider stack; static checks for formatting, lint, type checks, OpenAPI validation, and secret scanning; unit tests for backend and any frontend that ships them; integration tests against MongoDB, Redis, an object-storage emulator or test bucket, and the job lifecycle; security tests for authentication, role-based access control, webhook signatures, request limits, idempotency, and dependency-vulnerability scanning; build outputs for the backend image, the worker image where it is separate, the Web and Progressive Web App artifact, and the migration and index bundle; automatic Dev deployment from main with deployed smoke against Dev infrastructure and sandbox providers; release-candidate-only Test deployment with release gates against Atlas Staging and sandbox providers; and a manually approved production deployment that carries a changelog, a smoke plan, a rollback pointer, and a monitoring window.
| Stage | Required checks |
|---|---|
| Local pre-merge | deterministic unit/integration tests with local MongoDB, Redis, object-storage emulator, and fake providers. |
| Static checks | formatting, lint, typecheck, OpenAPI validation, secret scan. |
| Unit tests | backend unit tests, frontend unit tests where present. |
| Integration tests | MongoDB, Redis, object-storage emulator or test bucket, job lifecycle. |
| Security tests | auth/RBAC, webhook signatures, request limits, idempotency, dependency scan. |
| Build | backend image, worker image if separate, Web/PWA artifact, migration/index bundle. |
| Dev deploy | automatic from main after checks pass; runs deployed smoke against dev infrastructure and sandbox providers. |
| Test deploy | release candidate only; runs release gates against Atlas staging and sandbox providers. |
| Production deploy | manual approval, changelog, smoke plan, rollback pointer, and monitoring window. |
Versioning is uniform across the artefacts that ship together. The backend application-programming-interface image and worker image carry a semantic version or release tag plus the commit Secure Hash Algorithm hash; the Web and Progressive Web App build inherits the same release tag as the backend release candidate; the database index bundle is versioned with the backend release that requires it; Helm charts and manifests are versioned and pinned per environment; and the Infrastructure-as-Code modules are versioned with Infrastructure-as-Code commits and environment state.
Public beta requires evidence rather than guessing, so observability covers system health, user behaviour, job behaviour, provider behaviour, and support load with a single self-hosted stack. Metrics flow into Prometheus and are presented through Grafana dashboards. Logs flow into Loki as structured JavaScript Object Notation log records that carry request identifiers. Traces are emitted from the application-programming-interface and the workers through OpenTelemetry and exported to self-hosted Grafana Tempo on the observability node. Alerts are routed through Alertmanager to founder and operations channels. External uptime checks cover the application, the application-programming-interface, and critical flows. Privacy-conscious product analytics is separated by environment, and the support inbox correlates environment, user, request, and job identifiers.
Required dashboards cover an executive beta health view of signups, active users, upload starts and completions, preorder intents, support tickets, and critical errors; the application-programming-interface health view of requests per second, ninety-fifth and ninety-ninth percentile latency, error rate, saturation, top endpoints, and rate-limit rejections; the job health view of queue depth, oldest job age, runtime, failures by class, dead letters, and cancellation count; the MongoDB health view of Atlas CPU, memory, connections, read and write latency, slow queries, and index usage; the Vector Search health view of query count, ninety-fifth-percentile latency, timeout count, zero-result rate, and index size; the object-storage health view of upload sessions, completions, failed validations, growth, and egress estimate; the provider health view of language-model latency and error count and cost estimate, Stripe webhook success, and email-delivery failure rate; and the infrastructure health view of node CPU, memory, and disk usage, pod restart count, ingress status, certificate expiry, and backup status.
The critical alert catalogue is sized for a small operations team but covers every surface that can endanger the public beta. The application-programming-interface is considered down when the health endpoint fails for two minutes; high error rate triggers above two-percent five-hundred-class responses over five minutes; high latency triggers above one second at the ninety-fifth percentile over ten minutes. A stuck queue is the oldest light-job age above ten minutes or the heavy-job age above its configured Service Level Agreement. Any priority-zero or priority-one dead letter fires its own alert. MongoDB pressure fires when Atlas CPU or connections sit above planned thresholds for fifteen minutes. Vector Search failures fire above a two-percent timeout or error rate over ten minutes. Object-upload failures fire on completion or validation failure spikes. Disk pressure fires at seventy-five percent on any node and goes critical at eighty-five percent. Backup failures fire when a production backup job misses its window. Certificate expiry alerts at fourteen days remaining. Cost anomaly alerts fire when AI-provider or object-storage growth runs materially above its daily budget.
| Alert | Initial threshold |
|---|---|
| API down | health endpoint failing for 2 minutes. |
| API high error rate | 5xx above 2% for 5 minutes. |
| API latency | p95 above 1 second for 10 minutes. |
| Queue stuck | oldest light job above 10 minutes or heavy job above configured SLA. |
| Dead letters | any P0/P1 job dead-lettered. |
| MongoDB pressure | Atlas CPU or connections above planned threshold for 15 minutes. |
| Vector Search failures | timeout/error rate above 2% for 10 minutes. |
| Object upload failures | completion failure spike or validation failure spike. |
| Disk pressure | any node disk above 75%; critical above 85%. |
| Backup failure | any production backup job misses its window. |
| Certificate expiry | less than 14 days. |
| Cost anomaly | AI/provider or object-storage growth materially above daily budget. |
Security, abuse, and denial-of-service controls live in the infrastructure rather than relying solely on application code. Public static traffic is filtered by the Cloudflare content-delivery network and the Web Application Firewall managed rules. Application-programming-interface read endpoints carry per-Internet-Protocol-address and per-session limits at both the edge and the application-programming-interface itself. Authentication endpoints carry strict per-Internet-Protocol-address and per-identity throttling. Upload-session creation carries per-user daily quotas, per-Internet-Protocol-address burst limits, and file-size declaration validation. Direct uploads enforce presigned-URL expiry, content-length range, and Cross-Origin Resource Sharing restrictions. Heavy-job creation carries per-user and per-project concurrency caps. Language-model translation jobs carry per-user, per-project, and per-environment budget caps. Webhooks verify signatures, protect against replay, and use idempotency keys. Administration application-programming-interfaces enforce role-based access control, multi-factor authentication where the provider supports it, and audit logging.
The initial rate-limit catalogue is tuned from telemetry and abuse attempts: anonymous public application-programming-interface reads at one hundred and twenty requests per minute per Internet-Protocol-address, authenticated normal reads at six hundred per minute per user, mutating calls at one hundred and twenty per minute per user, authentication attempts at ten over ten minutes per Internet-Protocol-address and identity, upload-session creation at ten sessions per hour and thirty per day per user, model-processing job creation at three queued or running jobs per user and twenty per day during beta, language-model translation batch creation at a budget-based cap plus twenty batches per day per user until measured, and support ticket creation at ten per day per user plus three per hour per anonymous Internet-Protocol-address.
| Endpoint class | Limit |
|---|---|
| Anonymous public API reads | 120 requests/minute/IP |
| Authenticated normal API reads | 600 requests/minute/user |
| Mutating API calls | 120 requests/minute/user |
| Auth attempts | 10 attempts/10 minutes/IP and identity |
| Upload session creation | 10 sessions/hour/user and 30/day/user |
| Model-processing job creation | 3 queued or running jobs/user, 20/day/user during beta |
| LLM translation batch creation | budget-based plus 20 batches/day/user until measured |
| Support ticket creation | 10/day/user and 3/hour/IP anonymous |
Secrets at rest use Secrets OPerationS plus age for Phase A environment secrets, with no plaintext secrets in Git. Production shell access is restricted to the principal operator initially and time-boxed for contractors. Kubernetes access is separated into per-environment contexts with audited production administration access. Atlas access uses least-privilege database users scoped per service and per environment. Object-storage credentials are separated per bucket and per purpose where possible. Continuous Integration deployment credentials are environment-scoped, protected variables, and are never reused between Dev, Test, and Production.
Reliability rests on graceful degradation rather than overbuilding. When one application-programming-interface pod fails, Kubernetes restarts it and the load balancer routes around it. When one application-worker node fails, the application-programming-interface stays available on the other application node if capacity allows. A heavy-worker node failure pauses or retries heavy jobs while keeping the interactive application-programming-interface healthy. A Redis failure degrades cached data and rate counters but leaves durable state in MongoDB. A degraded Atlas returns safe degraded errors with bounded retries and protects user-facing writes. Degraded object storage degrades uploads and generated-asset reads while keeping the application-programming-interface otherwise available. A degraded language-model provider pauses or retries translation and generation without blocking the application-programming-interface. A Cloudflare issue triggers a documented emergency origin path only when switching Domain Name System and edge is practical.
The backup schedule combines Atlas-managed production backups with Atlas-restore drills before public beta and monthly during beta, encrypted etcd snapshots every six hours to the backup bucket, Git-tracked Kubernetes manifests and Helm values, daily object-storage inventory manifests, daily production support and export records to the backup bucket or provider export, and Git-tracked observability configuration. Recovery targets confirm the posture: an application-programming-interface deployment regression has no data-loss expectation and a thirty-minute rollback target; a MongoDB data restore aims for a fifteen-minute Recovery Point Objective and a four-hour Recovery Time Objective; a K3s control-plane rebuild aims for a six-hour Recovery Point Objective and a four-hour Recovery Time Objective; object-asset recovery aims for twenty-four hours and eight hours; and a full production rebuild from Infrastructure-as-Code and backups aims for twenty-four hours and one business day during beta.
Scaling is driven by metrics rather than intuition. The first response to an application-programming-interface ninety-fifth-percentile latency above eight hundred milliseconds with high CPU is more application-programming-interface replicas; the second is a worker or instance upgrade to CPX42 or CCX23. High ninety-fifth-percentile latency with low CPU first triggers inspection of MongoDB, Redis, provider latency, and slow queries, then addition of indexes, cache, or database tier. Application-worker CPU above seventy percent sustained adds a worker or a larger size, then splits the application-programming-interface and the light-worker node pools. A heavy queue older than thirty minutes first adds a heavy-worker replica if memory allows and then adds a second CCX23 heavy node. Heavy-job out-of-memory conditions reduce concurrency and memory-profile jobs before upgrading the heavy node or optimising the parser. Atlas CPU or memory pressure first optimises indexes and query shape and then upgrades the production Atlas tier to M30. Vector Search ninety-fifth-percentile latency above target first reduces top-k and improves filters, then adds dedicated Search Nodes or a higher Atlas tier. Object storage above the five-hundred-gigabyte planning target first enforces lifecycle and deduplication rules and then increases the allowance with a media-retention review. Low Cloudflare cache hit ratio first fixes cache headers and asset fingerprinting and then moves more safe public assets onto content-delivery network paths. Redis memory above seventy percent first reduces time-to-live values and key cardinality and then resizes or moves to a managed Redis. A saturated observability node first reduces retention and scrape cardinality and then moves to a larger node or external Software-as-a-Service.
| Trigger | First response | Second response |
|---|---|---|
| API p95 above 800 ms and CPU high | Add API replicas | Add app worker or upgrade to CPX42 / CCX23. |
| API p95 high but CPU low | Inspect MongoDB, Redis, provider latency, slow queries | Add indexes, cache, or database tier. |
| App worker CPU above 70% sustained | Add app worker or upgrade worker size | Split API and light-worker node pools. |
| Heavy queue older than 30 minutes | Add one heavy-worker replica if memory allows | Add second CCX23 heavy node. |
| Heavy jobs OOM or swap | Reduce concurrency and memory-profile jobs | Upgrade heavy node or optimize parser/voxelizer. |
| Atlas CPU/memory pressure | Optimize indexes and query shape | Upgrade production Atlas tier to M30. |
| Vector Search p95 above target | Reduce top-k, improve filters, inspect index | Add dedicated Search Nodes or higher Atlas tier. |
| Object storage exceeds 500 GB | Enforce lifecycle and dedup rules | Increase budget and review media retention. |
| Cloudflare cache hit ratio low | Fix cache headers and asset fingerprinting | Move more safe public assets to CDN paths. |
| Redis memory above 70% | Reduce TTLs and key cardinality | Resize Redis or move to managed Redis. |
| Observability node saturated | Reduce retention/scrape cardinality | Move observability to larger node or external SaaS. |
Implementation work is bounded by Infrastructure-as-Code from the start. OpenTofu or Terraform modules cover Hetzner projects, networks, firewalls, servers, the load balancer, and object storage; a Cloudflare module covers Domain Name System, Web Application Firewall, content-delivery network, and rate-limit rules; an Atlas project and cluster configuration procedure or Infrastructure-as-Code definition covers Staging and Production; pinned K3s bootstrap scripts produce rebuildable clusters; per-environment Helm values cover workload deployment; and the local developer stack contract is defined as a Docker Compose service set with the required fake providers.
The delivery order moves through eight milestones. The platform first defines the local developer stack and provisions the Dev deployed K3s plus the Dev MongoDB and search node, with acceptance against local fake-provider tests and against the Dev application-programming-interface, worker, Redis, dev object storage, sandbox providers, and observability running from deployed pods. It then adds Continuous Integration and Continuous Deployment automatic Dev deployment so a merge to main produces versioned images, deploys to Dev, and runs deployed health, application-programming-interface, job, and provider smoke. It provisions the test environment so release candidates can deploy to test against Atlas Staging and the test object storage. It adds release gates so smoke, integration, security, backup, and rollback gates run for test. It provisions the production cluster — K3s high-availability control plane, application workers, heavy worker, observability, load balancer, and Cloudflare hosts. It adds the manually approved production-deployment path with rollback pointer and monitoring window. It runs the beta readiness drill — restore drill, incident drill, load smoke, upload and job smoke, and alert drill. It then starts the public beta with production accepting real users and real preorder intent, with dashboards and support active.
The remaining provisioning inputs are account identifiers and product selections that do not change the infrastructure shape: the final production domain names, the Hetzner Object Storage endpoint and bucket names, the Cloudflare account and zone identifiers, the Atlas project identifiers and backup-option confirmation for the M10 Staging and M20 Production tiers, the provider project or account identifiers for language model, Stripe test and live, email and support, and analytics, and whether mobile builds require separate Expo Application Services infrastructure in Phase A.5.
The infrastructure described above closes the loop on the active project requirements. The React Native and Expo universal application is supported by a Web and Progressive Web App target that is tested first while the backend and infrastructure remain target-neutral for iOS and Android. Multilingual user input and language-model translation are supported by asynchronous translation queues, provider budgets, job observability, and durable translation records. Long-running model processing is supported by the heavy-worker pool, the job state model, concurrency caps, and an object-storage-based file flow. Security and denial-of-service coverage is provided by the Cloudflare Web Application Firewall, application-programming-interface limits, upload quotas, job quotas, secret separation, and private database, Redis, and K3s surfaces. Reliability and provider-failure handling are supported by retry budgets, circuit breakers, dead letters, degraded modes, and explicit backup and restore targets. Telemetry and support readiness are supported by metrics, logs, traces, customer-behaviour analytics, support correlation, and alerts. Real preorder intent before fulfilment is supported by a production environment that holds the data safely without requiring payment or fulfilment activation. The designer phase before real fulfilment is supported by infrastructure that carries designer content, publication, media, search, and preorder interest before any real order-fulfilment work.
| Source | Use |
|---|---|
| Hetzner Cloud API, checked 2026-05-14 with configured credentials | Instance availability, deprecation state, and baseline gross prices. |
Hetzner Object Storage documentation, https://docs.hetzner.com/storage/object-storage/ |
S3-compatible object-storage design assumption. |
Hetzner Object Storage product page, https://www.hetzner.com/storage/object-storage/ |
Object-storage product and pricing category validation. |
MongoDB Atlas pricing, https://www.mongodb.com/pricing |
Atlas tier cost estimates. |
MongoDB Atlas Vector Search documentation, https://www.mongodb.com/docs/atlas/atlas-vector-search/ |
Atlas Vector Search staging/production assumption. |
DomiDo backend specification, DD-BACKEND-SPEC-002 |
API, job, DB, security, telemetry, and reliability requirements. |
DomiDo universal requirements, DD-REQS-002 |
Phase A / Phase A.5 feature and target constraints. |