Saguaro Cloud Systems

Our work

Every project we can publish, anonymised. Each one lists what was built and the technology it ran on.

2024 onward

2020 to 2024

  • Sep 2023 to Jun 2024A standard monorepo for second-generation cloud functionsFintech and regulatedTypeScript, Nx, Cloud Functions
  • Aug 2022 to May 2024Schema checks and subgraph publication in the delivery pipelineFintech and regulatedTekton, GraphQL, Node
  • Jun 2022 to May 2024Self-hosted continuous-integration runners on the clusterFintech and regulatedGitHub Actions, Kubernetes, Helm
  • Mar 2022 to May 2024Per-pull-request preview environmentsFintech and regulatedTekton, Kubernetes, Helm
  • Feb 2022 to May 2024A continuous-integration platform on Kubernetes-native pipelinesFintech and regulatedTekton, Knative, Kubernetes
  • Jan 2021 to May 2024Observability and alerting standardized across the fleetFintech and regulatedPrometheus, Sumo Logic, Honeycomb
  • Jul 2020 to Dec 2023Provisioning for managed databases, streaming and the warehouseFintech and regulatedSpanner, Cloud SQL, Pub/Sub, BigQuery
  • Jun 2020 to May 2024GitOps delivery for a fleet of production servicesFintech and regulatedArgoCD, Helm, Kubernetes
  • Apr 2020 to May 2024Infrastructure as code across a cloud organizationFintech and regulatedTerraform, Atlantis, Google Cloud
  • Apr 2020 to Dec 2023A managed Kubernetes platform for product engineeringFintech and regulatedGKE, Helm, Terraform

2016 to 2020

  • Jan 2017 to Feb 2019Container adoption and production orchestrationMedia and high-trafficDocker, Kubernetes, Packer
  • May 2016 to Aug 2018An on-premises private cloud with self-service core servicesMedia and high-trafficOpenStack, Ansible, Terraform

2012 to 2016

  • Mar 2015 to Apr 2016An HPC compute cluster for an internal development cloudMedia and high-trafficKVM, xCAT, OpenHPC, Slurm
  • Jan 2015 to Dec 2016CDN configuration captured and audited under version controlMedia and high-trafficAkamai, Python, Subversion
  • Sep 2014 to Jun 2017Operational wrappers over load-balancer, firewall and storage APIsMedia and high-trafficPerl, Python, NetApp
  • Jun 2014 to Dec 2016Version-controlled DNS zone management for public and internal resolutionMedia and high-trafficBIND, Perl, Subversion
  • Jun 2014 to Jul 2015LDAPS directory refactored for multi-master replication across datacentersMedia and high-trafficOpenLDAP, Perl, Linux
  • Mar 2012 to Mar 2014Continuous integration across development, staging and productionMedia and high-trafficJenkins, PHPUnit, Selenium
  • Jan 2012 to Mar 2014Provisioning automation for physical and virtual hostsMedia and high-trafficPuppet, PXE, Kickstart, Bash

Before 2012

  • Aug 2011 to Mar 2014A configuration-management baseline across core servicesMedia and high-trafficPuppet, PostgreSQL, Apache, MySQL, Memcached
  • Jun 2011 to Sep 2013Heterogeneous virtualization consolidated onto one hypervisorMedia and high-trafficKVM, CentOS, libvirt
  • Mar 2010 to Dec 2010Migration of newly acquired sites into the hosting estateMedia and high-trafficLinux, Apache, MySQL
  • Jan 2010 to Dec 2010Configuration modules and versioned deployment for core web servicesMedia and high-trafficPuppet, Apache, MySQL, PostgreSQL
  • Nov 2009 to Dec 2010Filer and load-balancer operations for a high-traffic estateMedia and high-trafficNetApp, Big-IP, Linux

Six of these are written up in detail. The rest are listed with dates and technology.

Problems people call us about

Six situations we see often, taken from real projects and anonymised.

E-commerce & Direct-to-Consumer

You've outgrown a WordPress/WooCommerce store and want a fast headless storefront, but you don't want to build and secure your own checkout, and guest purchases (including ones made before an account exists) still have to unlock the right account, with refunds reversing access.

Rebuild the front end as a headless React/TypeScript storefront with checkout kept on a hosted commerce platform, served by a single Go service on Cloud Run. Purchases arrive as HMAC-verified webhooks that pass through an idempotency ledger and then three-way identity resolution, a signed token bridge, then an email match, then a pending-access queue claimed on next login, so even a guest checkout binds to an account, and refunds revoke entitlement by reason code.

  • Go
  • TypeScript
  • MySQL
  • Cloud Run
  • Secret Manager
  • Google Cloud

Enterprise SaaS & platform teams

As the fleet grows to hundreds of services across several regions, the platform team becomes the bottleneck: reliability and operational maturity are uneven and invisible, and engineers open tickets for basic questions like 'can this cluster reach that host on that port?'

Automate the maturity audit; score every service against a fixed rubric by mining Git, CI, and observability data, keeping the history in BigQuery so trends are queryable and served through a dashboard. Give engineers self-service network diagnostics that run from inside the target cluster as ephemeral Kubernetes Jobs (correct network position, torn down after each run), so the common answers no longer need a human in the loop.

  • Go
  • BigQuery
  • Kubernetes
  • GKE
  • Terraform
  • Google Cloud

Non-profit & education

Your system of record is a SaaS you can't modify, and it only emits a daily spreadsheet that's a 31-day rolling window rather than a running total, so summing snapshots double-counts and naively diffing them reports 'lost' donors who did nothing. The same data has to drive both a sensitive internal view and a public page that must not leak names or dollar figures.

Reconstruct the missing daily event stream by diffing consecutive snapshots, modeling window roll-off as its own category so gifts aging out aren't reported as churn, and refuse to compute the misleading cumulative total, naming every field for what's actually true of windowed data. Enforce the public/private split at the API boundary with a separate DTO that has no sensitive fields by construction, served as a stateless Next.js app on Cloud Run reading object storage through a bound service account, with computed results cached behind a short-TTL freshness check.

  • TypeScript
  • Cloud Run
  • Google Cloud

Fintech & regulated

Money moves through a third-party processor's webhooks, which retry and arrive out of order, so you risk double-provisioning and failing to reverse on refund, and auditors need every discrepancy visible. The data is regulated: it can't leave an approved region and secrets can't sit in the build artifact.

Claim an idempotency ledger keyed on (order, event) atomically before any side effect so a grant can never double-run, revoke on refund by reason code, and when a paid amount doesn't match the expected price still provision but record the discrepancy for reconciliation instead of silently failing a paying customer, plus alert on the silent-failure class where you correctly return 200 to the processor but a downstream step failed and no 5xx exists to catch it. For the data itself: verified TLS with a pinned CA and a startup check that reads the actually-negotiated cipher rather than trusting config, secrets fetched at runtime from a secret manager, and any automated state change gated behind human approval.

  • Go
  • PostgreSQL
  • Cloud Run
  • Secret Manager
  • Google Cloud

Media & high-traffic

Public read traffic is spiky and the read path recomputes expensive aggregates or hits a slow upstream on every request; meanwhile large file downloads on poor mobile networks get severed by default request timeouts and full-response buffering, and the public surface must never expose internal fields.

Cache computed results at TTLs tuned per surface, using a cheap short-TTL listing/version check as the freshness signal so you're never blind to new content for more than a few seconds, and run stateless containers on Cloud Run behind a global HTTPS load balancer with CDN-fronted object storage for assets. Enforce the public boundary with a dedicated DTO whose sensitive fields don't exist, and for large downloads raise the request timeout and remove any middleware that buffers the whole response, since serverless response-size limits will otherwise sever the stream.

  • Go
  • TypeScript
  • Cloud Run
  • Google Cloud

Teams adopting agentic AI / LLM assistants

You want to add an LLM assistant to an existing product or ops workflow, grounded in your own data rather than hallucinating, without runaway model cost, without the model taking a destructive action, and without prompt injection riding in through the data it reads.

Build tool-calling agents whose tools are read-only and grounded in your real datastore, so the model explains and recommends from tool output instead of memory, and route per role to the cheapest adequate model across vendors, cheap models for lookups, stronger ones for judgment, with the cost table written down. Keep every mutating action behind a human-approval gate and block destructive tools by default; harden the endpoint by treating tool output as data not instructions, whitelist-validating any user input that flows into a query, isolating sessions, fetching secrets at runtime, and pinning inference to an approved region.

  • Python
  • Go
  • Google ADK
  • Vertex AI
  • Google Cloud
  • Secret Manager

Teams whose infrastructure is changed by hand

Your estate was built through a console and the only record of who changed what is a chat message, so nobody can say with confidence what is running, and no environment can be rebuilt from scratch without the one person who remembers.

Put the estate under infrastructure as code and make the repository the system of record: modules for the shapes you repeat, a pull request as the unit of change with its plan attached for review, and reconciliation from version control so drift shows up rather than gets discovered. Tenancy and address allocation become things the code hands out instead of a spreadsheet somebody owns.

  • Terraform
  • Pulumi
  • Atlantis
  • ArgoCD
  • GitHub Actions

Teams where CI has become the constraint

Builds take long enough that people batch their changes, the pipeline is flaky often enough that a red run gets re-run instead of read, and there is no way to try a change against anything resembling production before it merges.

Move the pipeline onto Kubernetes-native tasks with runners on your own cluster, so capacity is a decision rather than a queue. Give every pull request a preview environment torn down with it, and move the checks that actually catch things, schema compatibility and contract tests, into the path to merge instead of after it.

  • Tekton
  • Knative
  • GitHub Actions
  • Kubernetes
  • Helm

Fleets nobody can see into

Metrics, logs and traces live in three different places, the alerts page on causes nobody recognises at three in the morning, and there is no consistent answer to which services are healthy or who owns them.

Standardise the telemetry: one set of conventions across metrics, logs and traces, and service level objectives written as symptoms a user would notice, so the page a person gets is one they can act on. Then score every service against a maturity rubric mined from Git, CI and the telemetry itself, so the gaps are a list with owners rather than an impression.

  • Prometheus
  • Grafana
  • Datadog
  • OpenTelemetry
  • BigQuery

Estates moving off on-premises or another cloud

You are carrying a datacentre or a second cloud you no longer want, the workloads on it were never written down, and the migration keeps stalling because nobody can say what will break.

Inventory what is actually running before anything moves, then land the target as code so the new estate is reproducible from its first day rather than its second year. Consolidate hypervisors, lift what lifts cleanly, rebuild what does not, and keep both sides serving until traffic has moved rather than until a date has passed.

  • Terraform
  • Pulumi
  • Azure
  • Google Cloud
  • KVM
  • OpenStack

Estates where every host is slightly different

The servers were built at different times by different people, the differences between them were never documented, and a change that works on one box fails on the next for reasons nobody can reconstruct afterwards.

Write the baseline as code and bring hosts to it in waves rather than all at once, with provisioning automated from bare metal upward so a rebuild is routine instead of an event. What is deployed and what is in version control stay the same thing, and the difference between two hosts becomes a diff somebody can read.

  • Ansible
  • Puppet
  • Packer
  • PXE
  • Linux

Networks that have outgrown their address plan

Ranges were handed out as they were asked for, two of them now overlap, DNS is edited by hand in a console, and connecting one more environment means an afternoon of working out what is still safe to use.

Rebuild the address plan with allocation automated rather than requested, and put public and internal zones under version control so every record has an author and a history. Delegation, naming and labelling become conventions the tooling applies instead of documents people are asked to remember, and egress, NAT and the edge rules get the same treatment.

  • Cloud DNS
  • BIND
  • IPAM
  • Shared VPC
  • Terraform

If one of these sounds like your situation, the next step is one call, about ninety minutes.

Start a conversation