<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: functors</title>
    <description>The latest articles on DEV Community by functors (@functors).</description>
    <link>https://dev.to/functors</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F13056%2F9a32e36a-b65f-4641-8941-837d948bb4c6.png</url>
      <title>DEV Community: functors</title>
      <link>https://dev.to/functors</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/functors"/>
    <language>en</language>
    <item>
      <title>Part 2: Hands-on tc Framework: Building a Full-Stack Async API with Pages</title>
      <dc:creator>Robert J. Berger</dc:creator>
      <pubDate>Fri, 17 Apr 2026 22:03:11 +0000</pubDate>
      <link>https://dev.to/functors/part-2-hands-on-tc-framework-building-a-full-stack-async-api-with-pages-3i9m</link>
      <guid>https://dev.to/functors/part-2-hands-on-tc-framework-building-a-full-stack-async-api-with-pages-3i9m</guid>
      <description>&lt;h3&gt;
  
  
  Introduction: The Practical Graph
&lt;/h3&gt;

&lt;p&gt;This post will show a practical, hands-on example that implements a serverless topology using the &lt;code&gt;tc&lt;/code&gt; (Topology Composer) framework. It supports synchronous entry points with asynchronous real-time updates. You will construct a REST API (API Gateway Routes) backed by a Lambda producer.&lt;/p&gt;

&lt;p&gt;This Lambda producer emits an event to a an EventBridge Bus, which the framework routes to an AppSync Channel for Websocket broadcast via a secondary notifier function.&lt;/p&gt;

&lt;p&gt;Finally will show how to include a Web GUI by incorporating S3/CloudFront &lt;code&gt;Pages&lt;/code&gt; for the frontend.&lt;/p&gt;

&lt;p&gt;By defining the system as a directed graph of logical connections rather than a list of static resources, &lt;code&gt;tc&lt;/code&gt; derives all IAM policies, event rules, and infrastructure glue automatically, enforcing “least privilege” algorithmically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites &amp;amp; Environment Setup
&lt;/h3&gt;

&lt;p&gt;Before we start, make sure you have the following in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS Account.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tc&lt;/code&gt; CLI &lt;a href="https://tc-functors.org/getting-started/installation/" rel="noopener noreferrer"&gt;installed&lt;/a&gt; (the Rust-powered engine behind this magic).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; (specifically for &lt;a href="https://docs.docker.com/build/" rel="noopener noreferrer"&gt;&lt;code&gt;buildx&lt;/code&gt;&lt;/a&gt; support).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Set up local dev environment
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;A Note on Environment:&lt;/strong&gt; This guide assumes you are working in a proper *nix environment (macOS or Linux). Only tested on macOS.&lt;/p&gt;

&lt;p&gt;Create a working directory and cd into it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; tc-rest-demo
&lt;span class="nb"&gt;cd &lt;/span&gt;tc-rest-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To set the context for this tutorial, copy and paste the following into your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SANDBOX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="nt"&gt;-dev&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NAMESPACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rest-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tc&lt;/code&gt; supports many conventions based on filenames and directory hierarchies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A topology.yml is always at the top of the working directory of the project&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Defining the Topology (&lt;code&gt;topology.yml&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The core of your Functor is the &lt;code&gt;topology.yml&lt;/code&gt;. This defines the graph: the logical connections where relationships are primary and infrastructure glue is derived algorithmically. There are currently 8 "atoms" that can be elements of a topology.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entity&lt;/th&gt;
&lt;th&gt;Cloud Mapping (AWS)&lt;/th&gt;
&lt;th&gt;The &lt;em&gt;So What?&lt;/em&gt; (Benefit)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Functions&lt;/td&gt;
&lt;td&gt;Lambda / ECS&lt;/td&gt;
&lt;td&gt;Pure business logic; side-effect free compute.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;States&lt;/td&gt;
&lt;td&gt;Step Functions&lt;/td&gt;
&lt;td&gt;The &lt;em&gt;managers&lt;/em&gt; handling flow control and error recovery.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Events&lt;/td&gt;
&lt;td&gt;EventBridge&lt;/td&gt;
&lt;td&gt;The &lt;em&gt;nerves&lt;/em&gt; of the system; decoupled signals.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routes&lt;/td&gt;
&lt;td&gt;API Gateway&lt;/td&gt;
&lt;td&gt;Synchronous HTTP entry points.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mutations&lt;/td&gt;
&lt;td&gt;AppSync (GraphQL)&lt;/td&gt;
&lt;td&gt;Modern data modification for frontends.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queues&lt;/td&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;td&gt;Buffering and load leveling between components.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels&lt;/td&gt;
&lt;td&gt;AppSync Events&lt;/td&gt;
&lt;td&gt;Real-time, two-way communication via Websockets.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pages&lt;/td&gt;
&lt;td&gt;S3 &amp;amp; CloudFront&lt;/td&gt;
&lt;td&gt;Static frontend assets (HTML/JS/CSS).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can compose these in the &lt;code&gt;topology.yml&lt;/code&gt; file. In general tc supports convention over configuration with sensible automatic defaults for many things. But these can also be overriden in the topology.yml or function.json files.&lt;/p&gt;

&lt;h4&gt;
  
  
  States (Orchestration)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents the flow control, error handling, and decision-making logic of a system. In the "Cloud Functor" model, &lt;code&gt;States&lt;/code&gt; coordinate tasks and delegate work to Functions or other subsystems, ensuring that business logic remains completely decoupled from the execution flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps directly to &lt;strong&gt;AWS Step Functions&lt;/strong&gt;. &lt;code&gt;tc&lt;/code&gt; automates the state machine definition and the complex IAM roles required for the state machine to transition between states and invoke other resources.&lt;/p&gt;

&lt;h4&gt;
  
  
  Functions (Business Logic / Compute)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represent pure business logic and act as side-effect-free compute units. They are the core computational workers of your topology where the actual application code lives and executes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;Lambdas&lt;/strong&gt; or &lt;strong&gt;ECS Containers&lt;/strong&gt;. &lt;code&gt;tc&lt;/code&gt; helps with the whole lifecycle of creating, maintaining and deploying Lambdas. There is support for a variety of languages, and packaging as it supports both zip and container image builds. We only use image builds for very large lambda images.&lt;/p&gt;

&lt;h4&gt;
  
  
  Events (Asynchronous Messaging)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents the "nerves" of the system—decoupled signals broadcast to interested subscribers without direct point-to-point dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;Amazon EventBridge&lt;/strong&gt;. &lt;code&gt;tc&lt;/code&gt; automates the creation of buses (or use of existing ones) and the definition of Rules that filter and route specific messages to targets (like queues or functions).&lt;/p&gt;

&lt;h4&gt;
  
  
  Routes (REST API Entry Points)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents synchronous HTTP entry points into the topology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;Amazon API Gateway&lt;/strong&gt; (REST APIs). &lt;code&gt;tc&lt;/code&gt; automates the creation of the API resources, methods (GET, POST, etc.), and the integration permissions required to invoke the backend logic.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mutations (GraphQL Operations)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents data modification operations, typically used in modern frontend-backend interactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;AWS AppSync&lt;/strong&gt; (GraphQL). &lt;code&gt;tc&lt;/code&gt; automates the schema definition and resolver mapping, allowing developers to define a "Mutation" that triggers a function or updates a data source.&lt;/p&gt;

&lt;h4&gt;
  
  
  Queues (Buffering)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents load leveling and asynchronous buffering between components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;Amazon SQS&lt;/strong&gt;. &lt;code&gt;tc&lt;/code&gt; automates the queue creation and the "glue" permissions allowing specific functions to produce to or consume from the queue.&lt;/p&gt;

&lt;h4&gt;
  
  
  Channels (Real-Time/Sockets)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents real-time communication pathways, allowing the server to push updates to clients (e.g., for chat apps or progress trackers).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;AWS AppSync Events&lt;/strong&gt; (Websockets). &lt;code&gt;tc&lt;/code&gt; automates the connection logic, allowing a topology to push messages to a "Channel" that connected frontend clients are subscribed to.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pages (Static Content)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Abstraction:&lt;/strong&gt; Represents the frontend assets or static UI components of the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt; Maps to &lt;strong&gt;Amazon S3&lt;/strong&gt; (storage) and &lt;strong&gt;CloudFront&lt;/strong&gt; (CDN). &lt;code&gt;tc&lt;/code&gt; manages the deployment of HTML/JS/CSS assets associated with the topology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Details:&lt;/strong&gt; In most serverless frameworks, the frontend is a second-class citizen; just some files you manually shove into a bucket. In &lt;code&gt;tc&lt;/code&gt;, the &lt;code&gt;Pages&lt;/code&gt; entity brings the UI into the graph.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Pages&lt;/code&gt; manages your static assets (HTML/JS/CSS) via S3 and CloudFront. To understand where this fits, look at our "Bones and Muscles" model. While you might use Terraform to build the "Bones": the heavy, static infrastructure like VPCs or RDS instances that provide rigidity &lt;code&gt;Pages&lt;/code&gt; is part of the "Muscles." These are the high-velocity components that provide the actual motion of your application.&lt;/p&gt;

&lt;p&gt;Unlike Terraform, which relies on a brittle local state file, &lt;code&gt;tc&lt;/code&gt; is stateless. It queries the "universe" (AWS) directly via the &lt;strong&gt;resolver&lt;/strong&gt;  to find those bones and attach the muscles. The &lt;code&gt;Pages&lt;/code&gt; entity automates the "magic spells" of the cloud: provisioning the S3 bucket, setting up the CloudFront CDN, and handling invalidations. You define the path, and the system ensures the UI is wired to the same logical topology as your API.&lt;/p&gt;

&lt;h4&gt;
  
  
  The "Graph-First" Automation
&lt;/h4&gt;

&lt;p&gt;The true power of &lt;code&gt;tc&lt;/code&gt; lies not just in creating these resources, but in automating the &lt;strong&gt;relationships&lt;/strong&gt; between them.&lt;/p&gt;

&lt;p&gt;If a developer defines a topology where a &lt;strong&gt;Route&lt;/strong&gt; triggers a &lt;strong&gt;Function&lt;/strong&gt;, which puts a message on a &lt;strong&gt;Queue&lt;/strong&gt;, &lt;code&gt;tc&lt;/code&gt; automatically compiles the necessary:&lt;/p&gt;

&lt;p&gt;API Gateway Integration.&lt;/p&gt;

&lt;p&gt;IAM Policies (e.g., &lt;code&gt;sqs:SendMessage&lt;/code&gt; scoped strictly to that queue).&lt;/p&gt;

&lt;p&gt;Event Source Mappings (connecting the Queue to a worker Function).This allows developers to define the system as a clean graph (Topology) while the tool handles the "spaghetti" of infrastructure configuration.&lt;/p&gt;

&lt;h4&gt;
  
  
  The "Pages" Entity: Frontend as a First-Class Citizen
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rest-demo&lt;/span&gt;
&lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./frontend&lt;/span&gt;  &lt;span class="c1"&gt;# Path to your static assets&lt;/span&gt;

&lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
    &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;processor&lt;/span&gt; &lt;span class="c1"&gt;# REST entry point maped to a Lambda function with the label processor&lt;/span&gt;

&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;processor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Definition of the Lambda function that handles the REST request&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handler.py&lt;/span&gt; &lt;span class="c1"&gt;# Specifies the entry point&lt;/span&gt;
    &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ProcessedEvent&lt;/span&gt; &lt;span class="c1"&gt;# Emits an EventBridge event signal when done&lt;/span&gt;

&lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ProcessedEvent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Definition of the EventBridge Event&lt;/span&gt;
    &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Updates&lt;/span&gt; &lt;span class="c1"&gt;# Routes the event to a Websocket channel&lt;/span&gt;

&lt;span class="na"&gt;channels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Definition of the AppSync Event Channel&lt;/span&gt;
    &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="c1"&gt;# Appsync Events for real-time delivery&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this graph, the &lt;strong&gt;composer&lt;/strong&gt;  sees that a &lt;code&gt;route&lt;/code&gt; calls a &lt;code&gt;function&lt;/code&gt;, which emits an &lt;code&gt;event&lt;/code&gt;, which triggers a &lt;code&gt;channel&lt;/code&gt; update. You aren't writing IAM policies or configuring EventBridge rules; you are describing how the data flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Build Process: Bundling Logic
&lt;/h3&gt;

&lt;p&gt;Once your topology is defined, you run &lt;code&gt;tc build&lt;/code&gt;. This command packages your business logic into deployable artifacts using the &lt;strong&gt;builder&lt;/strong&gt; .&lt;/p&gt;

&lt;p&gt;If the Lambda function is relatively simple, like in our example here, there are little to no library dependencies, at least none that have CPYTHON or other transitive dependencies that require compiling/linking. In this simple case, &lt;code&gt;tc&lt;/code&gt; build will just bundle up using &lt;em&gt;Docker buildx&lt;/em&gt; all the Python (or other interpreted language) code in a standard ZIP file as for normal AWS Lambda images.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;tc&lt;/code&gt; uses &lt;code&gt;Docker buildx&lt;/code&gt; for multi-architecture support (linux/amd64), your builds are consistent whether you’re on your laptop or running in a CI/CD pipeline. No more "it worked on my machine" excuses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the Async Response &amp;amp; Progress Tracking
&lt;/h3&gt;

&lt;p&gt;By integrating &lt;code&gt;Pages&lt;/code&gt; with &lt;code&gt;Channels&lt;/code&gt;, we stop making the user stare at a loading spinner. Instead of a black-box backend that leaves the UI hanging, we make the application feel alive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initiating the Request:&lt;/strong&gt; The &lt;code&gt;Pages&lt;/code&gt; frontend sends a POST request to the &lt;code&gt;/request&lt;/code&gt; route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async Processing:&lt;/strong&gt; The &lt;code&gt;processor&lt;/code&gt; function acknowledges the request immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tracking Progress:&lt;/strong&gt; As the function works, it emits events. These "nerves" of the system travel through the graph to the AppSync &lt;code&gt;Channel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-Time Feedback:&lt;/strong&gt; The frontend listens to the Websocket &lt;code&gt;Channel&lt;/code&gt;. The UI updates in real-time as the backend moves through stages, providing a seamless, responsive experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algorithmic IAM Policies &amp;amp; Roles
&lt;/h3&gt;

&lt;p&gt;One of the biggest headaches in AWS is writing "brittle bones" IAM policies. Usually, developers get lazy and use wildcards (&lt;code&gt;Resource: *&lt;/code&gt;), creating a "Confused Deputy" problem where services are tricked into acting maliciously.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tc&lt;/code&gt; kills this problem through &lt;strong&gt;Algorithmic Authorization&lt;/strong&gt;. The &lt;strong&gt;composer&lt;/strong&gt;  uses tested templates to automatically infer the intent of your graph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It sees the &lt;code&gt;Route&lt;/code&gt; points to a &lt;code&gt;Function&lt;/code&gt; and generates the &lt;code&gt;lambda:InvokeFunction&lt;/code&gt; permission.&lt;/li&gt;
&lt;li&gt;It sees the &lt;code&gt;Function&lt;/code&gt; emits to an &lt;code&gt;Event&lt;/code&gt;, so it generates &lt;code&gt;events:PutEvents&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It adds &lt;code&gt;aws:SourceArn&lt;/code&gt; condition keys to trust policies automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The compiler generates &lt;strong&gt;mathematically correct&lt;/strong&gt; policies scoped to exact ARNs. You literally cannot forget a security condition because you don't write the JSON: the system derives it from the relationship.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment: Moving into the Cloud
&lt;/h3&gt;

&lt;p&gt;To move your Functor into the cloud, we use &lt;code&gt;tc create&lt;/code&gt; and &lt;code&gt;tc update&lt;/code&gt;. Let’s cut to the chase: &lt;code&gt;tc&lt;/code&gt; does not manage a local state file. Instead, the &lt;strong&gt;resolver&lt;/strong&gt; uses the AWS SDK to query the "universe" to find the ARNs of your "Bones" (VPC, etc.) and wires your "Muscles" to them.&lt;/p&gt;

&lt;p&gt;Run the following command to deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tc create &lt;span class="nt"&gt;--sandbox&lt;/span&gt; &lt;span class="nv"&gt;$SANDBOX&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; &lt;span class="nv"&gt;$AWS_PROFILE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you change the code or the topology graph, run &lt;code&gt;tc update&lt;/code&gt;. The resolver will detect what changed in the cloud and apply only the necessary updates to the "muscle" layer, making the iteration cycle nearly instantaneous.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrap Up: The Cloud is Your Computer
&lt;/h3&gt;

&lt;p&gt;In just a few steps, we have deployed a full-stack, event-driven application with a secured REST API and an async, Websocket-enabled frontend. By using a single graph definition, we’ve eliminated the manual "spaghetti" of infrastructure glue.&lt;/p&gt;

&lt;p&gt;We’ve seen how &lt;code&gt;Functions&lt;/code&gt; (Pure Logic), &lt;code&gt;Events&lt;/code&gt; (Nerves), and &lt;code&gt;Pages&lt;/code&gt; (UI) work together. Turns out, once you stop fighting low-level primitives and start thinking in graphs, building complex systems becomes way too easy. You are no longer an infrastructure manager; you are a cloud programmer.&lt;/p&gt;

&lt;p&gt;Stay tuned for &lt;strong&gt;Part 3&lt;/strong&gt;, where we will cover &lt;code&gt;States&lt;/code&gt; the "Managers" (Step Functions) that handle flow control and error recovery in truly massive fractal architectures.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tc&lt;/code&gt; Documentation:  &lt;a href="https://tc-functors.org/" rel="noopener noreferrer"&gt;https://tc-functors.org/&lt;/a&gt;&lt;br&gt;
&lt;code&gt;tc&lt;/code&gt; Github: &lt;a href="https://github.com/tc-functors/tc" rel="noopener noreferrer"&gt;https://github.com/tc-functors/tc&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud</title>
      <dc:creator>Robert J. Berger</dc:creator>
      <pubDate>Fri, 17 Apr 2026 18:39:06 +0000</pubDate>
      <link>https://dev.to/functors/intro-to-tc-cloud-functors-a-graph-first-mental-model-for-the-modern-cloud-3o17</link>
      <guid>https://dev.to/functors/intro-to-tc-cloud-functors-a-graph-first-mental-model-for-the-modern-cloud-3o17</guid>
      <description>&lt;p&gt;This is the first part of a multipart series introducing &lt;em&gt;&lt;a href="https://github.com/tc-functors" rel="noopener noreferrer"&gt;tc Cloud Functors&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;em&gt;Monolith in the Desert&lt;/em&gt; Problem
&lt;/h2&gt;

&lt;p&gt;Sometimes I feel like the Forrest Gump of computing, having worked on or been around everything from the introduction of mini and microcomputers to starting an ISDN ISP in 1993, pioneering international server farms, and building early e-commerce sites through the earliest days of the cloud, working with AWS in 2008. (and so much more!)* Since then I've specialized in serverless infrastructure and systems.&lt;/p&gt;

&lt;p&gt;About three years ago, I joined a startup called &lt;a href="https://www.informediq.com" rel="noopener noreferrer"&gt;Informed&lt;/a&gt;, whose product is a very sophisticated Intelligent Document Processing pipeline for lenders. Informed had the classic situation of a startup that has found its market with a working product, but the implementation is a mirror of the &lt;em&gt;random walk&lt;/em&gt; they took to discover their market/product fit. They were processing about 8% of all US car loans, dealing with heavy bank regulations, and had the terrifying constraint of &lt;em&gt;infinite PII&lt;/em&gt;. Yet, the tech stack was a typical startup tangle: a massive Ruby on Rails app sitting at the center of the universe, talking to just about every AWS service imaginable through Elastic Beanstalk, and using a single Postgres database as a message bus. I don't say this with disdain. It was a working system that had lots of quality engineering and had been very successful in delivering services to some of the top banks and generating profits.&lt;/p&gt;

&lt;p&gt;Most startups have this random wandering in the desert until they find their product/market fit, and their software tends to follow the same route. Unfortunately, it was also a nightmare of tech debt where adding a single feature felt like moving a mountain.&lt;/p&gt;

&lt;p&gt;We knew we had to move to a modular, event-driven architecture, but we weren't just talking about a couple of functions. We were looking at a future that now consists of &lt;strong&gt;107 topologies&lt;/strong&gt; and &lt;strong&gt;340 Lambdas&lt;/strong&gt; across Python, Ruby, and Node. Managing that kind of complexity for a small team of developers is the real hurdle. Traditional tools like &lt;code&gt;CloudFormation&lt;/code&gt; which, frankly, I find to be a collection of frustrating &lt;em&gt;magic spells&lt;/em&gt;. Using CloudFormation felt like trying to build a high-performance engine out of low-level, brittle bones. Even Terraform, while it &lt;em&gt;sucks less&lt;/em&gt;, didn't have the right impedance match for the high-velocity &lt;em&gt;muscle&lt;/em&gt; of a distributed serverless system.&lt;/p&gt;

&lt;p&gt;We knew we wanted to move to a more unified and serverless style of infrastructure. The use case matched serverless perfectly, as its API driven, machine-to-machine work primarily. It's very bursty and follows the normal sine wave pattern of the US business hours. We also found that the existing tooling did not lend itself to building such complex serverless systems.&lt;/p&gt;

&lt;p&gt;Before we had &lt;code&gt;tc&lt;/code&gt; our developers were spending 80% of their time manually &lt;em&gt;wiring&lt;/em&gt; infrastructure and only 20% writing logic; we had already lost. We needed to stop managing resources and start programming the cloud as a single computer. This frustration with manual wiring led us to a breakthrough: moving away from resource lists and toward a &lt;em&gt;graph-first&lt;/em&gt; mental model.&lt;/p&gt;

&lt;p&gt;Amazingly, company management approved the rewrite, and we actually were successful with first customers on it after 6 months and fully switched to the new system in 9 months. It was during this time that tc was developed based on our real needs and experiences. We continue to add new features as we discover the needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mental Shift: From Resources to Graphs
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;Aha! Moment&lt;/em&gt; happens when you realize most tools ask the wrong question. They focus on the &lt;em&gt;implementation&lt;/em&gt; (the &lt;em&gt;how&lt;/em&gt;) rather than the &lt;em&gt;intent&lt;/em&gt; (the &lt;em&gt;what&lt;/em&gt;). I scoured the &lt;em&gt;InterTubes&lt;/em&gt; for something better, but everything else was still resource-centric.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question Asked&lt;/th&gt;
&lt;th&gt;Primary Focus&lt;/th&gt;
&lt;th&gt;Outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Resource-First (Terraform/CloudFormation)&lt;/td&gt;
&lt;td&gt;&lt;em&gt;What resources do you need?&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;A static list of primitives (buckets, roles) that must be manually wired.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Function-First (Serverless Framework)&lt;/td&gt;
&lt;td&gt;&lt;em&gt;What functions do you have?&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;A collection of compute units that still require manual infrastructure &lt;em&gt;glue&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph-First (tc)&lt;/td&gt;
&lt;td&gt;&lt;em&gt;What is the graph of your system?&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;A logical topology where relationships are primary and infrastructure is derived algorithmically.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Think of it like the &lt;strong&gt;React analogy&lt;/strong&gt;. Before React, we manually manipulated the DOM (the infrastructure). With React, we focus on component state and relationships; the &lt;em&gt;DOM manipulation&lt;/em&gt; is just a side effect handled by the framework. In the &lt;code&gt;tc&lt;/code&gt; model, you describe how components connect, and the system handles the IAM roles, event rules, and subscriptions as derivative artifacts. It’s an inversion of control where the graph is the truth. To make this graph-based thinking concrete, we created a single unit of encapsulation: the &lt;strong&gt;Cloud Functor&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Cloud Functor?
&lt;/h2&gt;

&lt;p&gt;We borrowed the term &lt;em&gt;functor&lt;/em&gt; from &lt;em&gt;OCaml’s&lt;/em&gt; parameterized modules. In our world, a &lt;strong&gt;Cloud Functor&lt;/strong&gt; is a first-class, composable unit of infrastructure. To understand it, just look at your file system as a similar model of hierarchy and other characteristics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Namespaced&lt;/strong&gt;: Just like a directory, every functor has a unique identifier to keep things organized and domain-specific.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandboxed&lt;/strong&gt;: You can deploy isolated versions (dev, staging, feature-branch) in the same deployment account without collision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Versioned&lt;/strong&gt;: We use Git tags and deployment manifests to &lt;em&gt;freeze&lt;/em&gt; implementations, making rollbacks as simple as pointing to a previous tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isomorphic&lt;/strong&gt;: The definition is abstract; the same YAML renders consistently whether it's on your laptop or in production.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;File System Analogy&lt;/strong&gt; shows how you work through &lt;em&gt;Sub-Tree Autonomy&lt;/em&gt;. You can &lt;code&gt;cd&lt;/code&gt; into a deeply nested folder, say, &lt;code&gt;src/loan-app/extraction/ssn-id&lt;/code&gt; and run &lt;code&gt;tc create&lt;/code&gt; or &lt;code&gt;tc update&lt;/code&gt; in that directory. The tool treats that subfolder as the &lt;em&gt;root of the universe&lt;/em&gt;, ignoring the rest of the 340-Lambda monolith. This &lt;em&gt;zooming&lt;/em&gt; allows for infinite nesting in a fractal pattern; a top-level orchestrator delegates to sub-orchestrators, and every level looks the same. Every one of these functors is built from the same set of &lt;em&gt;atomic&lt;/em&gt; building blocks.&lt;/p&gt;

&lt;p&gt;Breaking away from the file system analogy, the top feature of Cloud Functors is their &lt;em&gt;Composability&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 8 Atoms of the Cloud Universe
&lt;/h2&gt;

&lt;p&gt;We identified eight core entities that are sufficient to build any sophisticated serverless topology.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entity&lt;/th&gt;
&lt;th&gt;Cloud Mapping (AWS)&lt;/th&gt;
&lt;th&gt;The &lt;em&gt;So What?&lt;/em&gt; (Benefit)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Functions&lt;/td&gt;
&lt;td&gt;Lambda / ECS&lt;/td&gt;
&lt;td&gt;Pure business logic; side-effect free compute.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;States&lt;/td&gt;
&lt;td&gt;Step Functions&lt;/td&gt;
&lt;td&gt;The &lt;em&gt;managers&lt;/em&gt; handling flow control and error recovery.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Events&lt;/td&gt;
&lt;td&gt;EventBridge&lt;/td&gt;
&lt;td&gt;The &lt;em&gt;nerves&lt;/em&gt; of the system; decoupled signals.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routes&lt;/td&gt;
&lt;td&gt;API Gateway&lt;/td&gt;
&lt;td&gt;Synchronous HTTP entry points.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mutations&lt;/td&gt;
&lt;td&gt;AppSync (GraphQL)&lt;/td&gt;
&lt;td&gt;Modern data modification for frontends.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queues&lt;/td&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;td&gt;Buffering and load leveling between components.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels&lt;/td&gt;
&lt;td&gt;AppSync Events&lt;/td&gt;
&lt;td&gt;Real-time, two-way communication via WebSockets.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pages&lt;/td&gt;
&lt;td&gt;S3 &amp;amp; CloudFront&lt;/td&gt;
&lt;td&gt;Static frontend assets (HTML/JS/CSS).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By defining these logical connections, the &lt;em&gt;spaghetti&lt;/em&gt; of infrastructure glue is derived algorithmically. This isn't just a convenience; it’s the secret to killing some of the most common security headaches in the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composability - The Real Superpower of tc
&lt;/h2&gt;

&lt;p&gt;Let's cut to the chase about the real superpower of &lt;code&gt;tc&lt;/code&gt;: graph-based &lt;em&gt;composability&lt;/em&gt;. Turns out, when you stop thinking in terms of disjointed infrastructure resources and start treating your cloud primitives: &lt;code&gt;functions&lt;/code&gt;, &lt;code&gt;events&lt;/code&gt;, &lt;code&gt;queues&lt;/code&gt;, and &lt;code&gt;routes&lt;/code&gt; as fundamental &lt;em&gt;atoms&lt;/em&gt;, you can build some truly elegant, self-documenting systems.&lt;/p&gt;

&lt;p&gt;One simply defines the logical connections between these &lt;em&gt;namespaced&lt;/em&gt; and &lt;em&gt;sandboxed&lt;/em&gt; entities in a clean YAML graph, and the &lt;code&gt;tc composer&lt;/code&gt; works its magic spells to infer all the complex IAM permissions and infrastructure glue for you. Because these relationships are elevated to explicit, first-class citizens rather than being scattered as obscure implementation details, the topology definition itself becomes a highly readable architecture diagram where no low-level infrastructure configuration leaks into your business logic.&lt;/p&gt;

&lt;p&gt;This means we can seamlessly compose these atomic entities into higher-order &lt;code&gt;Cloud Functors&lt;/code&gt;, and then recursively compose &lt;em&gt;those&lt;/em&gt; into massive enterprise systems, allowing my team to understand an entire topology of 30+ interconnected microservices at a glance without ever wading through the spaghetti code of traditional IaC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithmic Security: Killing the &lt;em&gt;Confused Deputy&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;In the trenches, I see developers &lt;em&gt;just getting it working&lt;/em&gt; by stripping away &lt;code&gt;SourceArn&lt;/code&gt; or &lt;code&gt;ExternalId&lt;/code&gt; conditions because IAM is hard. This creates the &lt;em&gt;confused deputy&lt;/em&gt; problem, where a service is tricked into acting on behalf of a malicious party.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;tc&lt;/code&gt; &lt;strong&gt;composer&lt;/strong&gt;  solves this using &lt;strong&gt;Algorithmic Security&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tested Templates&lt;/strong&gt;: The composer uses pre-validated, secure policy templates for every connection. It automatically adds &lt;code&gt;SourceArn&lt;/code&gt; condition keys to trust policies. You literally cannot forget them because you don't write them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Least Privilege by Default&lt;/strong&gt;: Since the graph knows Function A only talks to Queue B, the compiler generates a policy scoped strictly to those ARNs. No wildcards (&lt;code&gt;*&lt;/code&gt;) allowed.&lt;/p&gt;

&lt;p&gt;Because you define the &lt;strong&gt;topology&lt;/strong&gt; (logic) and not the &lt;strong&gt;policy&lt;/strong&gt; (implementation), the compiler always regenerates the algorithmically secure version. While &lt;code&gt;tc&lt;/code&gt; handles the &lt;em&gt;muscle&lt;/em&gt;, we still need a skeleton to hold everything up.&lt;br&gt;
You still need someone with an understanding of IAM roles/policies to create the templates, but the enforcement is done by the tooling.&lt;/p&gt;
&lt;h2&gt;
  
  
  The &lt;em&gt;Bones and Muscles&lt;/em&gt; Hybrid Architecture
&lt;/h2&gt;

&lt;p&gt;We don't try to replace Terraform (at least not yet!). Instead, we use a hybrid model that respects different infrastructure velocities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bones (Terraform)&lt;/strong&gt;: This is your skeleton—heavy, static stuff like VPCs, RDS, and the &lt;strong&gt;Event Bus&lt;/strong&gt;. You want your bones to be rigid and reliable. We will run Terraform to set up and maintain these static elements. We do not run Terraform regularly and don't really use it for drift management. Not only that, but we expect to eventually have tc be able to create and manage all AWS elements (and maybe other clouds someday).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Muscles (tc)&lt;/strong&gt;: These are the high-velocity parts: Lambdas, Step Functions, and the &lt;strong&gt;Rules/Subscriptions&lt;/strong&gt; on that bus. They attach to the bones and provide the actual motion. &lt;code&gt;tc&lt;/code&gt; manages this fully&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Tendons (The Resolver)&lt;/strong&gt;: This is the magic. The &lt;code&gt;tc resolver&lt;/code&gt; queries the &lt;em&gt;universe&lt;/em&gt; (AWS) to find the ARNs of the &lt;em&gt;bones&lt;/em&gt; as well as the state of the deployed functors and all the previously deployed services. &lt;code&gt;tc&lt;/code&gt; talks directly to AWS via the AWS SDKs. The &lt;em&gt;resolver&lt;/em&gt; then uses that data to supply ARNs or other info needed to wire things up.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Developer Workflow: &lt;code&gt;Zooming&lt;/code&gt; into Action
&lt;/h2&gt;

&lt;p&gt;The workflow is designed for speed. Because the &lt;code&gt;tc builder&lt;/code&gt; uses &lt;strong&gt;Docker buildx&lt;/strong&gt; for multi-architecture support (Linux/amd64), your builds are consistent regardless of your local machine or build by CI/CD in the Cloud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tc build    &lt;span class="c"&gt;# Package logic and ML models (Docker multi-arch)&lt;/span&gt;
tc publish  &lt;span class="c"&gt;# Push assets like Layers and EFS models to S3&lt;/span&gt;
tc create   &lt;span class="c"&gt;# Provision the isolated, namespaced sandbox&lt;/span&gt;
tc invoke   &lt;span class="c"&gt;# Test logic directly in the cloud via a REPL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three pillars of this workflow are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandboxing&lt;/strong&gt;: Collision-free environments (e.g., &lt;code&gt;dev-your-name&lt;/code&gt;). Alice’s messages never end up in Bob’s queue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contextual Execution&lt;/strong&gt;: &lt;em&gt;Zoom&lt;/em&gt; into a sub-folder and iterate in seconds, ignoring the rest of the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isomorphic Rendering&lt;/strong&gt;: The same YAML is used for your local dev sandbox and production. No more &lt;em&gt;it worked on my machine&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up: The Cloud is the Computer
&lt;/h2&gt;

&lt;p&gt;At the end of the day, the goal is to stop being &lt;em&gt;infrastructure managers&lt;/em&gt; and start being &lt;em&gt;cloud programmers&lt;/em&gt;. When we moved to this graph-first model at Informed, our implementation speed just zoomed. Being spoiled by Ruby and other high-level languages, I couldn't go back to manual wiring. We are now integrating LLMs/Agents with tc both for dev and targets, so things should go even faster.&lt;/p&gt;

&lt;p&gt;Turns out, once you stop fighting with low-level primitives and start thinking in graphs, building complex systems becomes far too easy. It’s truly a superpower. Stop thinking in resource lists. Start thinking in graphs. The cloud is your computer; it's time to start programming it properly.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tc Cloud Functors&lt;/code&gt; is an open source project that can be found at &lt;a href="https://github.com/tc-functors" rel="noopener noreferrer"&gt;https://github.com/tc-functors&lt;/a&gt; with documentation at &lt;a href="https://tc-functors.org/" rel="noopener noreferrer"&gt;https://tc-functors.org/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>devops</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
