Case study

Taste Platform

A recommendation API that ran on managed AWS services for a summer, then was rebuilt to need none of them. The cloud design survives as a parameterised reference rather than a running bill.

Constraint

A recommendation API that owes nothing to a provider

Shape

The supported runtime is a single Python service. It binds to loopback, keeps profile history in SQLite, and exposes health, profile, history, recommendation and chat endpoints. Recommendations come from a local catalogue combined with the ratings and tags already in the profile.

A local model can be switched on. If it is absent or fails, deterministic scoring remains, so the degraded mode is the one that was there from the start rather than an emergency path nobody tested.

Network exposure is explicit: a strong token sent as a request header, a firewall or authenticated proxy in front, and the database treated as private profile history.

Python, SQLite, Docker, AWS CDK as reference

Replacement

What each managed service became

  • API Gateway and Lambda became one local service, or the Docker container.
  • DynamoDB became SQLite on disk.
  • A Bedrock agent became deterministic scoring, or a local model.
  • Cognito became a token header on trusted local clients.
  • Secrets Manager and KMS became an owner-only environment file plus the host's own storage controls.
  • An EventBridge and SNS digest became a host timer with local mail.

History

It ran on managed services first

Phase one

Between May and August 2026 the platform ran in eu-west-1 as a seven-stack CDK architecture: a managed agent for chat, DynamoDB for persistence, API Gateway in front of the functions with JWT authentication from a managed identity pool, private-only subnets, and an audit trail. Keys were customer-managed, no policy carried a wildcard, and the browser held its token in memory rather than in storage. The interface was a self-hosted PWA reachable only over a private network.

It was then rebuilt provider-free for public release. That is the part worth saying out loud: the local runtime is not a prototype that never grew up, it is the second version of something that already worked on managed services, and the architecture was kept as reference instead of being thrown away.

Discipline

Keeping a cloud architecture honest without running it

What the deployed phase left behind, and the rules that keep the stacks honest now that nothing is running.

  • No account identifier is embedded in source. It is resolved from explicit context or the environment at synthesis time.
  • Model and alias identifiers are stack parameters, so a different environment is a different input rather than a different branch.
  • The streaming path accepts an existing role. It takes a role ARN instead of creating a long-lived user, because an architecture that mints credentials to make a demo work is the one that leaks them later.
  • Synthesis is a local check; deployment is a billable action. The handbook requires reviewing permissions, model identifiers, regions, cost, retention, deployment order and deletion policy before any deploy, and the cloud end-to-end test is excluded from the normal suite because it needs a live stack.

Boundary

What it deliberately is not

Scope

Nothing of this is running in the cloud today, and the page claims no users, no measured accuracy and no engagement: the deployed phase was a personal build, not a service with an audience. The local runtime is the part that runs now, and the part the tests cover.