<?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: Alexander Rey</title>
    <description>The latest articles on DEV Community by Alexander Rey (@alexander0042).</description>
    <link>https://dev.to/alexander0042</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%2Fuser%2Fprofile_image%2F1211683%2Fd885642c-35b2-4e1e-aa94-5fcc8334ccd7.jpeg</url>
      <title>DEV Community: Alexander Rey</title>
      <link>https://dev.to/alexander0042</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexander0042"/>
    <language>en</language>
    <item>
      <title>Keeping Pirate Weather Afloat: Inside the AWS Pipeline and the Christmas Eve Outage</title>
      <dc:creator>Alexander Rey</dc:creator>
      <pubDate>Wed, 22 Apr 2026 15:30:47 +0000</pubDate>
      <link>https://dev.to/aws-builders/keeping-pirate-weather-afloat-inside-the-aws-pipeline-and-the-christmas-eve-outage-1g51</link>
      <guid>https://dev.to/aws-builders/keeping-pirate-weather-afloat-inside-the-aws-pipeline-and-the-christmas-eve-outage-1g51</guid>
      <description>&lt;p&gt;Since it's been a while since I last covered Pirate Weather's AWS infrastructure, I thought it was time to write a short update on how everything fits together, and also explain where things have gone wrong. At a high level, Pirate Weather is a Python script that reads Zarr files. These files are created from a series of scripts that run on a schedule, download the data, perform some light processing, and save .zip files for the response script. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ingestion &amp;amp; Processing:&lt;/strong&gt; A suite of Python scripts runs on a precise schedule, triggered by &lt;strong&gt;Amazon EventBridge&lt;/strong&gt;. These scripts are orchestrated by &lt;strong&gt;AWS Step Functions&lt;/strong&gt;, which manage &lt;strong&gt;AWS Fargate&lt;/strong&gt; containers (using our &lt;a href="https://gallery.ecr.aws/j9v4j3c7/pirate-wgrib-python-arm" rel="noopener noreferrer"&gt;custom ARM-based image&lt;/a&gt;). These containers download raw data, perform light processing, and "chunk" the data into Zarr format for lightning-fast retrieval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage Strategy:&lt;/strong&gt; The processed Zarr data is initially persisted as zip files on &lt;strong&gt;Amazon S3&lt;/strong&gt;. To minimize latency, an &lt;strong&gt;rclone&lt;/strong&gt; container syncs these files to &lt;strong&gt;autoscaled EC2 NVMe instances&lt;/strong&gt;. 

&lt;ul&gt;
&lt;li&gt;By serving data from local NVMe storage rather than directly from S3, we achieve the IOPS necessary for real-time weather requests.&lt;/li&gt;
&lt;li&gt;Using zip files avoids the having a ton of S3 objects and the associated transaction costs.&lt;/li&gt;
&lt;li&gt;Notably, the time for each model forecast is included in every chunk, which avoids having to rely on metadata. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;ECS service:&lt;/strong&gt; An ECS service coordinates four containers running on the EC2 instances: rclone for syncing, the &lt;a href="https://gallery.ecr.aws/j9v4j3c7/pirate-alpine-zarr" rel="noopener noreferrer"&gt;production FastAPI container&lt;/a&gt;, the development container, the historic data (Time Machine) container, and Kong.

&lt;ul&gt;
&lt;li&gt;This ensures that things are restarted if there are issues, handles placement on the instances, and container updates.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Traffic Management &amp;amp; Security:&lt;/strong&gt; Inbound requests are routed through &lt;strong&gt;Amazon CloudFront&lt;/strong&gt; to a &lt;strong&gt;Network Load Balancer (NLB)&lt;/strong&gt;, which passes it to the EC2 instances. From there, traffic hits a &lt;strong&gt;Kong Gateway&lt;/strong&gt; container, which manages authentication and rate limiting.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Data Persistence:&lt;/strong&gt; The gateway and API layers are supported by &lt;strong&gt;Amazon ElastiCache (Redis)&lt;/strong&gt; for rapid session/rate-limit caching and an &lt;strong&gt;Amazon RDS&lt;/strong&gt; database for persistent metadata and user information.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPirate-Weather%2Fpirateweather%2Fblob%2Fmain%2Fdocs%2Fimages%2FArch_Diagram_2026.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPirate-Weather%2Fpirateweather%2Fblob%2Fmain%2Fdocs%2Fimages%2FArch_Diagram_2026.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's quite a few nuances to the various pieces; however, this is "meat and potatoes" of it. &lt;/p&gt;

&lt;h4&gt;
  
  
  December 24, 2025 downtime incident
&lt;/h4&gt;

&lt;p&gt;The four hour production downtime had two root causes. The first was traced to a configuration conflict between our AWS Step Function definitions and the underlying ECS cluster strategy. While our ECS cluster is architected to run a resilient 50:50 mix of Fargate Spot and Fargate On-Demand instances, the Step Function definition responsible for triggering the ingestion tasks contained an explicit override. As seen in the configuration snippet below, the task was hardcoded to rely exclusively on &lt;code&gt;FARGATE_SPOT&lt;/code&gt;. During a period of high Spot instance reclamation in our availability zone, these ingestion containers were repeatedly terminated by AWS before completion, halting the data pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"CapacityProviderStrategy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"CapacityProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FARGATE_SPOT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an issue on it's own; however, should have been recoverable; however, the ingestion failure was amplified by a logic error in the processing scripts, which lacked a fallback mechanism for missing GFS data when the two day buffer was exceeded, causing the forecast generation to fail entirely rather than serving stale or partial data. To resolve this, I have updated all Step Function task definitions to remove the explicit &lt;code&gt;CapacityProviderStrategy&lt;/code&gt; override. The tasks now defer to the ECS cluster’s default capacity provider strategy, ensuring a stable 50:50 distribution between Spot and On-Demand instances. This change guarantees that even if Spot capacity is volatile, the On-Demand instances will ensure the ingestion process completes successfully. I've also added additional logging on when ingest tasks fail, which will avoid missing failures in the underlying data, as well as a check to avoid serving stale model results (&lt;a href="https://github.com/Pirate-Weather/pirate-weather-code/pull/542" rel="noopener noreferrer"&gt;PR #542&lt;/a&gt;). &lt;/p&gt;

</description>
      <category>weather</category>
      <category>aws</category>
    </item>
    <item>
      <title>Navigating Stormy Seas: Troubleshooting Pirate Weather’s Container Memory Usage with AWS Container Insights</title>
      <dc:creator>Alexander Rey</dc:creator>
      <pubDate>Thu, 20 Mar 2025 18:23:31 +0000</pubDate>
      <link>https://dev.to/alexander0042/navigating-stormy-seas-troubleshooting-pirate-weathers-container-memory-usage-with-aws-container-31pl</link>
      <guid>https://dev.to/alexander0042/navigating-stormy-seas-troubleshooting-pirate-weathers-container-memory-usage-with-aws-container-31pl</guid>
      <description>&lt;p&gt;Running applications in containers provides numerous benefits—easy deployments, rapid scaling, streamlined updates, and more. However, troubleshooting and maintaining observability can become challenging, especially when containers run in cloud environments. Issues that didn't surface during testing might appear suddenly in production, and without direct access to underlying processes, diagnosing root causes can quickly become complex. This exact scenario happened to us recently at Pirate Weather, where unexpected container failures led to brief and seemingly random downtime incidents.&lt;/p&gt;

&lt;p&gt;As outlined previously in our infrastructure overview, Pirate Weather’s production stack is hosted on Amazon Elastic Container Service (Amazon ECS), utilizing a series of ECS tasks managed by a single ECS service. Our service ensures high availability by maintaining at least two tasks running at all times, each task consisting of three distinct containers. Behind these tasks, we leverage auto-scaling EC2 instances to handle dynamic workloads.&lt;/p&gt;

&lt;p&gt;When we began experiencing intermittent downtime, our initial investigation revealed ECS tasks failing with the infamous "Error 137," indicating that containers were terminated due to exceeding memory limits. Although this was a helpful clue, we still didn't know which specific container was responsible or whether the issue stemmed from sudden memory spikes or gradual leaks.&lt;/p&gt;

&lt;p&gt;Initially, our monitoring setup involved using the Kong Prometheus plugin, but this provided insights only at the API gateway level, not deep within our ECS infrastructure. Seeking a more comprehensive solution, we discovered &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html" rel="noopener noreferrer"&gt;AWS Container Insights&lt;/a&gt;, a built-in feature of Amazon CloudWatch that offers detailed metrics and logs for containers running on Amazon ECS.&lt;/p&gt;

&lt;p&gt;Enabling AWS Container Insights was incredibly straightforward—just a single click in our ECS task definition settings, a quick update to our ECS service, and within minutes, we had detailed container-level metrics on CPU utilization, storage I/O, and crucially, memory usage available directly in CloudWatch. Arguably one of the easiest yet most impactful updates we’ve ever made!&lt;/p&gt;

&lt;p&gt;After collecting data for a couple of days (and observing several more restarts), we revisited CloudWatch. The depth of data was impressive—almost overwhelming at first glance—but by filtering on key parameters like ClusterName, ContainerName, and ServiceName, we quickly identified the culprit. Our "TimeMachine" container, responsible for handling historical data requests, was steadily leaking memory and occasionally experiencing significant spikes. These spikes caused it to exceed its allocated memory, resulting in container termination and subsequent stack downtime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPirate-Weather%2Fpirateweather%2Fraw%2Fmain%2Fdocs%2Fimages%2FCloudWatch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FPirate-Weather%2Fpirateweather%2Fraw%2Fmain%2Fdocs%2Fimages%2FCloudWatch.png" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While a complete, permanent solution requires deeper investigation into the memory leak, AWS Container Insights provided immediate actionable insights, enabling us to implement two effective short-term solutions:&lt;/p&gt;

&lt;p&gt;We modified our task definition to include the --limit-max-requests=25 flag in our Uvicorn Docker command, automatically restarting worker processes within the container to mitigate the slow memory leak.&lt;/p&gt;

&lt;p&gt;We leveraged ECS's newly available container &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-restart-policy.html" rel="noopener noreferrer"&gt;restart policy&lt;/a&gt;, enabling graceful restarts of our TimeMachine container upon memory overload events. This ensured only the problematic container restarted rather than impacting the entire ECS task.&lt;/p&gt;

&lt;p&gt;Though further work is needed for a long-term fix, activating AWS Container Insights significantly streamlined our troubleshooting process, demonstrating the immense value this tool offers for quickly diagnosing and resolving container-related issues.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Faster, better, cheaper: lessons from three years of running a serverless weather API</title>
      <dc:creator>Alexander Rey</dc:creator>
      <pubDate>Sun, 31 Mar 2024 16:19:21 +0000</pubDate>
      <link>https://dev.to/aws-builders/faster-better-cheaper-lessons-from-three-years-of-running-a-serverless-weather-api-1fc8</link>
      <guid>https://dev.to/aws-builders/faster-better-cheaper-lessons-from-three-years-of-running-a-serverless-weather-api-1fc8</guid>
      <description>&lt;p&gt;Since launching Pirate Weather in 2021, I have learned an incredible amount about some of the upsides and downsides to running a weather API. Some things have worked well, some have not, but overall, it has been an unparalleled experience. While I’ve written a number of blog posts about specific aspects of this service, I wanted to take some time to put a few stray thoughts together about topics that are important, but not enough to write a whole post about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traffic spikes- good news and bad news
&lt;/h2&gt;

&lt;p&gt;Thanks to some incredibly exiting press coverage, Pirate Weather was made the internet rounds last year! One of the upsides to an AWS serverless infrastructure is that capacity scales to meet demand; however, the challenge is that there’s often hidden links that limit things. So, for my first lesson learned, it’s that I should have done more load testing, since things don’t always calmly build up to let you find the hidden, limiting links with time to spare. &lt;br&gt;
In particular, I ran into three main issues that contributed to downtime:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Signups flow, and specifically email. It turns out that AWS imposes a default limit of 50 outgoing messages per day unless the quota is raised, and so after that was hit, my signup service (the API Gateway Portal) was unable to confirm new accounts, preventing new users from coming on board. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EFS capacity. Pirate Weather relies on EFS burst credits to keep the shared file system humming along between the new model data coming online and forecast requests. EFS credits are generated automatically based on the amount of data stored on the share, and I try to keep this balanced. However, when there was a burst of traffic then the share run out of credits, and throughput slowed way down, knocking the service offline. The quick fix was to switch to a provisioned file system, which allows me to set a minimum throughput and regenerate the burning credits rapidly and setting a cloud watch alarm to alert me when they’re running low. Longer term, this is addressed permanently in version two by switch to different systems for model data ingest (S3] and serving data (local NVME), to make sure that one doesn’t overwhelm the other. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, a time-honoured lesson that can’t be repeated enough is not to rely on single availability zone (AZ) services. When my primary AZ went down last year, I didn’t have things set up to run in a second AZ, and so the service went down. Luckily, AWS has a ton of tools for making things run in multiple availability zones, and so now my EFS share spans multiple zones, as does my lambda response!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Monitoring
&lt;/h2&gt;

&lt;p&gt;Another great aspect of serverless computing is how easy it is to monitor things! I tried around with a few different services, but eventually settled on Grafana. They have a generous free tier, and by running the agent on a tiny EC2 instance it is able to query my Kong API Gateway containers to grab metrics from them. &lt;/p&gt;

&lt;p&gt;This is then paired with their AWS account integration to grab some key metrics from Lambda and EFS, ensuring that I have a complete picture of how everything is running in one dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Costs
&lt;/h2&gt;

&lt;p&gt;One of the best parts of getting some Pirate Weather press was that Corey Quinn noticed my service and offered to take a look at my setup to see where costs could be optimized! His company, The Duckbill Group, is pretty well unparalleled at deciphering AWS bills and optimizing services. Now, Pirate Weather runs a pretty lean operation (I originally built it to fit in the AWS free tier), so I wasn’t sure if he would find much to optimize, with just a few containers, a EFS share, and a lambda function… I was very wrong. &lt;br&gt;
There were four primary insights that he identified with my setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Sagemaker. You might be wondering why I had a sagemaker instance running when that’s not part of the infrastructure, as was I! It turns out that it’s very, very easy to leave these notebooks running, and they’re not cheap. I’d mucked around with one one day (link to AWS blog) and forgotten to completely disable it, so that was a quick and easy fix. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ClousWatch logs. This was another area where it hadn’t occurred to me to look for costs, but it turns out this service can add up quickly. I’d added a few print statement to help debug a couple of processing scripts, as well as my main API response, and while these logs were great for fixing issues, they also ended up adding up. By streamlining what was being ingested and what the retention period was, this bill was trimmed right down. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API Gateway. AWS API Gateway is a truly phenomenal service. It let me get a public API off the ground and running with almost no setup or overhead and was the perfect solution for years. However, this comes at a (literal) cost, and the downside is that per request cost isn’t cheap. This was a longer-term fix, but ultimately resulted in me moving over to the Kong API gateway, which also allowed the service to scale past 10,000 users!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One for ARM and ARM for one! Speaking of containers, most of the data ingest and processing happens in Fargate containers, and Corey pointed out that ARM containers are an objectively better choice when possible. Since my processing scripts were all Python, with some light tweaking I was able to move my ingest over to this container type. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All these changes saved on billing costs, which is great in and of itself, but he also had some broader insight on improving my setup. There’s no one rule to optimizing AWS bills, with way more nuance than I ever imagined, and it was invaluable having him to take a look!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deploying Kong Gateway (OSS) in Production on AWS Using serverless Tools</title>
      <dc:creator>Alexander Rey</dc:creator>
      <pubDate>Fri, 17 Nov 2023 13:55:09 +0000</pubDate>
      <link>https://dev.to/aws-builders/deploying-kong-gateway-oss-in-production-on-aws-using-serverless-tools-72a</link>
      <guid>https://dev.to/aws-builders/deploying-kong-gateway-oss-in-production-on-aws-using-serverless-tools-72a</guid>
      <description>&lt;h3&gt;
  
  
  You can bring a data scientist to a database, but you can’t make them an administrator
&lt;/h3&gt;

&lt;p&gt;Weather APIs can be intricate, dealing with a myriad of data flowing in and out. At  &lt;a href="https://pirateweather.net" rel="noopener noreferrer"&gt;Pirate Weather&lt;/a&gt;, my background in data processing equipped me to handle file operations with Python, but delving into the realm of cloud infrastructure was an entirely new challenge. While I am familiar enough with the command line and know the basics of AWS, I started this without experience in networking or databases, and frankly, I wasn't eager to learn. This meant that serverless tools were an ideal solution, letting me abstract away the infrastructure complexities and focus on actual building.&lt;/p&gt;

&lt;p&gt;Initially, AWS API Gateway was an incredible tool, full stop. It let me rapidly deploy Pirate Weather as a functioning API using little more than a Lambda function and a URL, which was exactly what I was looking for at the time. It was easy to set up, very high performant, and allowed just the right amount of customization. However, two years post-launch, Pirate Weather started to come up against the API key limit imposed by AWS API Gateway, and the developer portal I was using had been depreciated. This meant that it was time to find a new solution, and Kong Gateway was exactly what I was looking for!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Kong?
&lt;/h3&gt;

&lt;p&gt;Why Kong Gateway (OSS)? Five main reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud native. Kong is designed to run in containers and has built in support for AWS Lambda, which meant it fit right in with my existing infrastructure.&lt;/li&gt;
&lt;li&gt;Scalable. Running in containers, Kong is more than capable of handling as many requests as I could throw at it and doesn’t have any key limitations.&lt;/li&gt;
&lt;li&gt;Compatible. My awesome registration provider (&lt;a href="https://www.apiable.io/" rel="noopener noreferrer"&gt;Apiable&lt;/a&gt;) already supported it as a backend, and the API is very straightforward.&lt;/li&gt;
&lt;li&gt;Customization. Kong supports custom plug-ins, which let me use a URL based API Key as authentication.&lt;/li&gt;
&lt;li&gt;Open Source! It felt wrong to put an open weather API behind a proprietary gateway, so this was an added plus.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;Implementing this was a significant undertaking, and I relied heavily on other published walkthroughs, so I wanted to take the time to explain the process here. At a high level, the architecture is straightforward: a network load balancer in front of a containerized Fargate service interacting with a cache, database, and Lambda function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96mnfqltth9nwwyat7vk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96mnfqltth9nwwyat7vk.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Image
&lt;/h3&gt;

&lt;p&gt;The system starts with a lightly customized &lt;a href="https://gallery.ecr.aws/j9v4j3c7/pirate-kong" rel="noopener noreferrer"&gt;Kong OSS image&lt;/a&gt;, which is build using Docker on an EC2 ARM instant and a very simple dockerfile:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

FROM kong:3.2-ubuntu
USER root
COPY kong-plugin-request-transformer_1251-0.4-1.all.rock /tmp/kong-plugin-request-transformer_1251-0.4-1.all.rock
WORKDIR /tmp
RUN luarocks install kong-plugin-request-transformer_1251-0.4-1.all.rock
USER kong


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Why the custom image? By default, the “Request Transformer” plugin runs after authentication; however, I needed it to run beforehand to extract the API key from a URL string. Specifically, the plugin adds a header from a URI capture: apikey:$(uri_captures['apikey']). This required that I create a ever so slightly modified version of the built in transformer &lt;a href="https://github.com/Kong/kong/tree/a382576530b7ddd57898c9ce917343bddeaf93f4/kong/plugins/request-transformer" rel="noopener noreferrer"&gt;built in transformer&lt;/a&gt; with a &lt;a href="https://docs.konghq.com/gateway/latest/plugin-development/custom-logic/#handlerlua-specifications" rel="noopener noreferrer"&gt;priority of 1251&lt;/a&gt; so it would run beforehand. By downloading the request transformer files, I could adjust the priority and &lt;a href="https://github.com/luarocks/luarocks/wiki/Creating-a-rock" rel="noopener noreferrer"&gt;build a new rock&lt;/a&gt;. The created the file that gets copied over and installed in the dockerfile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;Now that I had a functioning image, the AWS infrastructure falls into place around it. Kong stores everything in a Postgres database, and while I could have spun up my own, it was easier to rely on the AWS option, Aurora Postgres. Since the load is relatively small, I’m using the smallest Serverless v2 option, which uses 0.5 Aurora Capacity Units. By running this on RDS, it means I don’t have to worry about database updates, maintenance, or backups, and it will scale if there’s ever a wave of traffic.&lt;/p&gt;

&lt;p&gt;Kong can also rely on Redis for caching API calls or authentication. While I’m not caching any data yet, caching authentication quotas did produce a slight performance improvement, and allow for quotas to stay in sync when multiple instances of the Kong instance are running or if it gets restarted. For this, I spun up a simple, single node t4g instance, which provides a primary endpoint that Kong uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Container
&lt;/h3&gt;

&lt;p&gt;With the AWS infrastructure in place, it was time to get to Kong. At the core, it is an ECS service that calls &lt;a href="http://pirateweather.net/en/latest/Blog/KongGatewayInfrastructure/#container" rel="noopener noreferrer"&gt;task definition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This calls the public image with a few environmental variables referencing the database and cache. The service is designed to run as many copies of this task as required, scaling them up and down as needed. In terms of networking, the containers are assigned a public IP address, which allows the image to be pulled, and are otherwise attached to a private subnet. I also had to configure security groups to allow access to the database, cache, and Lambda function.&lt;/p&gt;

&lt;p&gt;With the basic Kong container in place, it was time to get traffic two and from it! At the front end, a Network Load Balancer interfaces between the broader internet and however many Kong containers are currently running. It’s configured to distribute traffic evenly between functioning containers, and Route53 is used to set the DNS for api.pirateweather.net to this load balancer or a fallback (more on that in a minute). For the back-end, I configured Kong to pass requests to a Lambda function using their built in plugin and a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc-endpoints.html" rel="noopener noreferrer"&gt;Lambda endpoint&lt;/a&gt; in my VPC. I did all the Kong setup using the wonderful &lt;a href="https://github.com/pantsel/konga" rel="noopener noreferrer"&gt;Konga&lt;/a&gt; running in a docker container on a management EC2 VM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fallback
&lt;/h3&gt;

&lt;p&gt;While this setup is designed to be resilient and reliable, I’m always thinking about possible failures, and Route53 has a tool built specifically for this! By adding in a healthcheck, Route53 will either return the DNS for the Elastic Load Balancer, or in case there’s an issue with my Konga setup, fall back to AWS API HTTP Gateway. This does not provide quota management or allow for new registrations but keeps things running at a baseline level.&lt;/p&gt;

&lt;p&gt;Compared to the regular AWS API Gateway, this setup has advantages and disadvantages. The always on database, container, and cache result in a slightly higher bill than before; however, this should remain relatively flat with increased usage. It’s equally fast, provides a wider range of customisation options, and scaled past the 10,000th key without missing a beat! In six months of production this setup has been rock solid, easily handling more than 20 million requests per month.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apiable
&lt;/h3&gt;

&lt;p&gt;Sitting alongside all of it is &lt;a href="https://www.apiable.io/" rel="noopener noreferrer"&gt;Apiable&lt;/a&gt;. This service was exactly what I was looking for to replace my depreciated AWS developer portal, handling registration, signups, and quota plans. Their service interfaces with my Kong admin API via the same port/ load balancer but a &lt;a href="https://docs.konghq.com/gateway/latest/admin-api/" rel="noopener noreferrer"&gt;different endpoint within Kong&lt;/a&gt;, so all I had to do to connect the two was create an admin consumer API key and point the URL to the correct place.&lt;/p&gt;

</description>
      <category>kong</category>
      <category>ecs</category>
      <category>aws</category>
      <category>weather</category>
    </item>
  </channel>
</rss>
