cloudonaut Monthly - October 2026: Goodbye API Gateway!
Last month, we announced that we would replace the Amazon API Gateway in front of our virus and malware scan API. October was all about that. Learn more about the new architecture and why Aurora DSQL - which we praised last month - did not make the cut. Besides that, we tried out the brand-new AWS Lambda Web Functions and the not-quite-so-new Lambda MicroVMs and will share our thoughts on those new compute options.

We are Michael and Andreas, two brothers who run widdix, the software company behind bucketAV, attachmentAV, HyperEnv and marbot. For more than ten years, we have been writing about how to build on AWS. cloudonaut Monthly gives you insights into our day-to-day work at widdix. We share our insights into challenges and wins, from both a technical and a business perspective.
The new architecture of our virus and malware scan API
Our Virus and Malware Scan API offering emerged from add-ons we built for bucketAV customers. To provide customers with a unified API for synchronous and asynchronous scans, we came up with the following architecture.
- API Gateway routing requests to an ALB for synchronous scans or to a Lambda function for asynchronous scans.
- The Lambda function submits scan jobs to a SQS queue.
- A fleet of EC2 instances fetches scan jobs from the SQS queue and processes them.
- The ALB distributes synchronous scan requests among a fleet of EC2 instances.
We used usage plans and API keys to implement monthly request quotas and request throttling.

As our Virus and Malware Scan API offering grew significantly and is serving more than 200 customers nowadays, it was about time to overcome two major flaws of the architecture.
- The API Gateway adds latency and costs.
- The API Gateway limits the request size to 10 MB and the request timeout to 29 seconds by default, which can be increased to 60 seconds upon request.
To overcome those limitations, we came up with the following architecture.
- An ALB distributes incoming synchronous and asynchronous scan jobs among a fleet of EC2 instances.
- The EC2 instances answer all API requests and perform synchronous scans.
- The EC2 instances submit asynchronous scan jobs to a SQS queue.
- A fleet of EC2 instances receives and processes asynchronous scan jobs.

But how to implement quotas and throttling?
All API and synchronous scan instances share one Valkey cache (ElastiCache). Each API request makes one atomic Lua script call to it, and that call does the auth check, rate limiting and quota counting together.
Throttling uses a token bucket per subscription.
- Each subscription’s plan sets three values: bucket size, refill amount and refill period.
- Each request takes one token. Tokens come back in whole refill periods, up to the bucket size.
- When the bucket is empty, the request gets 429 and a Retry-After header saying when the next refill happens.
- The cache server’s clock is used, so differences between instance clocks don’t matter.
- All API keys of a subscription share one bucket.
The quota is a fixed-window monthly counter per subscription.
- There is one counter per subscription per calendar month (UTC). It simply goes up with each counted request.
- Only scans count, and only when they weren’t throttled. When the counter reaches the plan’s limit, scans get 429.
- Other calls, such as polling for results or checking usage, use the token bucket but don’t count toward the quota.
DynamoDB instead of Aurora DSQL
ElastiCache is a great choice for implementing request throttling and quotas with minimal effect on latency, but ElastiCache is not an option to reliably persist subscriptions and API keys. Therefore, we were looking for a database system. As illustrated in the following figure, the approach is to store subscriptions and API keys in DynamoDB and use Lambda Event Functions to synchronize the data to ElastiCache with both an event-driven approach (DynamoDB Streams) and scheduled (EventBridge Scheduler and Step Functions).

Last month, we shared our thoughts about Aurora DSQL, a promising and simple to use Serverless database offering by AWS. We thought about making Aurora DSQL our go-to-database for Serverless workloads. For the new architecture of the Virus and Malware Scan API, we needed a database to persist subscriptions and API keys. First, we thought about adding Aurora DSQL to our architecture.
But then, we realized that Aurora DSQL is not available in all regions yet. The following table shows all regions that do not yet support Aurora DSQL.
| Area | Regions |
|---|---|
| US | us-west-1 (N. California) |
| Europe | eu-central-2 (Zurich), eu-south-1 (Milan) |
| Asia Pacific | ap-east-2 (Taipei), ap-south-2 (Hyderabad), ap-southeast-3 (Jakarta), ap-southeast-5 (Malaysia), ap-southeast-6 (New Zealand), ap-southeast-7 (Thailand) |
| Middle East | il-central-1 (Tel Aviv), me-central-1 (UAE)me-south-1 (Bahrain) |
| Africa | af-south-1 (Cape Town) |
| Latin America | mx-central-1 (Mexico) |
| Separate partitions | cn-north-1 and cn-northwest-1 (China), us-gov-east-1 and us-gov-west-1 (GovCloud), eusc-de-east-1 (European Sovereign Cloud) |
That’s why we decided to go with DynamoDB to avoid running into issues when deploying our Virus and Malware Scan API into additional regions in the future.
In summary, we are quite happy with the results. We were able to reduce latency for every API request. Besides that, we are ready to accept larger files for synchronous scans which we plan to make available for customers soon. The next challenge is to roll out the new architecture without any service interruptions. We are planning to do so in the coming weeks.
Lambda Web Functions and MicroVMs
AWS announced two variants of AWS Lambda within the past six months: Lambda Web Functions and MicroVMs.
MicroVMs: A MicroVM is an isolated, long-lived Amazon Linux VM for each tenant or session, started almost instantly from a snapshot. It suspends when idle, keeping memory and disk, with no compute charges (only snapshot storage is billed). Think of Lambda MicroVMs as a mixture of ECS Fargate and Lambda Event Functions.
Web Functions: A Web Function runs a standard Node.js HTTP server on Lambda behind a managed TLS endpoint. Each environment serves up to 128 concurrent requests (64 by default) and scales to zero. Immutable revisions enable canary releases, and endpoints can span multiple regions. Think of Web Functions as a long-running web server process that gets scaled automatically. Like a combination of API Gateway and Event Functions.
The following table shows a brief comparison of Event Functions - what we formerly just called AWS Lambda - with the new offerings Web Functions and MicroVMs.
| Event Functions (classic Lambda) | Web Functions | MicroVMs | |
|---|---|---|---|
| Unit of work | A handler invoked with one event | An HTTP server serving requests | A long-lived VM per tenant, session or job |
| Programming languages | Managed runtimes for Node.js, Python, Java, .NET and Ruby; Go, Rust and others through the OS-only runtime or container images | Node.js only (nodejs24.x), with any Node.js web framework such as Express, Fastify, Next.js or Koa | Any language you can install on Amazon Linux 2023 through the Dockerfile |
| Invoked by | Triggers, event source mappings (SQS, Kinesis, …), API or SDK | HTTPS requests to an endpoint domain | HTTPS to its endpoint, plus run/suspend/resume/terminate APIs |
| Programming model | handler(event, context) | Standard HTTP server on AWS_LAMBDA_HTTP_ENDPOINT | Any application in a Dockerfile |
| State | Ephemeral; the environment may be reused | Ephemeral; environments come and go with traffic | Memory and disk kept across suspend and resume |
| Typical use | Event processing, glue code, queue and stream consumers | Web apps and APIs | Per-tenant sandboxes, user sessions, stateful or long-running jobs, code execution |
Lambda Web Functions in Action
We started working on a dashboard for the Virus and Malware Scan API to give customers insights into usage and to allow to rotate API keys. The dashboard is a simple web application, and therefore a good fit for giving AWS Lambda Web Functions a try.
The following figure illustrates the architecture consisting of the following building blocks.
- CloudFront is the public entrypoint supporting custom domains and TLS certificate.
- S3 for hosting static assets like CSS, images, and so on.
- Lambda Web Functions for dynamic rendered content.
- DynamoDB to store and query data.

Getting started with Lambda Web Functions was a blast. Probably, the simplest way to deploy a web application on AWS.
Unfortunately, Web Function endpoints do not support custom domain names. Therefore, CloudFront is required to make Web Functions accessible under a custom domain. In my view, this has two drawbacks: a) additional costs per request, and b) CloudFront processes the data outside the region configured for Web Functions. This is a drawback, for example, in terms of GDPR compliance, since data processing within the EU cannot be guaranteed. So we are putting custom domain names for Web Function endpoints on our wishlist.
MicroVMs in Action
After having so much fun with Lambda Web Functions, I decided to give Lambda MicroVMs a try as well. Being able to spin up an isolated compute environment within a few seconds seemed to be a great choice for HyperEnv, our solution for self-hosted GitHub runners on AWS. So, I quickly built a proof of concept by building a HyperEnv variant that spins up MicroVMs instead of EC2 instances.
The following figure illustrates the architecture.
- GitHub sends a webhook event to an API Gateway.
- The API Gateway invokes a Lambda Event Function.
- The Lambda Event Function starts a Lambda MicroVM.
- The MicroVM starts the GitHub runner.
- The GitHub runner registers itself and processes a job.
- After completing the job, the MicroVM terminates.

Getting started with MicroVMs is a little trickier compared to Web Functions. Nevertheless, I was impressed that self-hosted runners started on MicroVM were available in less than 10 seconds. A significant improvement compared to EC2.
Lambda MicroVMs sound amazing. But here is the catch. Pricing is brutal. The following table shows the compute costs for 1 vCPU (Graviton) and 2 GiB memory in eu-west-1.
| $/min | |
|---|---|
| Lambda MicroVMs | 0.0022 |
| ECS Fargate | 0.00066 |
| EC2 (c7g.medium) | 0.00065 |
Of course, we are comparing apples with oranges here. For example, Lambda MicroVMs scale vertically up to 4x the baseline capacity. You are getting charged for the baseline capacity plus the additionally consumed compute usage. So, Lambda MicroVMs allow you to reduce the provisioned compute capacity compared to ECS Fargate and EC2 in some scenarios.
Nevertheless, paying more than three times the price of ECS Fargate for Lambda MicroVMs is ridiculous.
In my opinion, Lambda MicroVMs are a promising approach. However, the pricing is way off the mark.
What else we have been working on
Besides the big topics, here is what kept us busy in October:
- attachmentAV SDK for PHP: We released a Virus and Malware Scan SDK for PHP, including examples for Laravel and Symfony, and wrote about how to scan uploads for viruses in Laravel.
- attachmentAV for Salesforce: Releases 1.75.0 to 1.77.0 handle the Salesforce limit on asynchronous Apex executions, improve the setup instructions and check the refresh token policy of the connected app.
- bucketAV 3.6.0: New releases for both scan engines, ClamAV and Sophos.
- HyperEnv 3.7.0: Improved handling of EC2 Spot interruptions and the latest GitHub runner. We also fixed an edge case where GitHub delivered webhook events in the wrong order.
- marbot: Enriched alerts for Amazon Bedrock, Amazon Managed Service for Apache Flink and GuardDuty.
- Tax compliance on the AWS Marketplace: A follow-up to last month’s issue: we no longer download hundreds of listing fee invoices from an email attachment. Our automation now fetches them via the AWS Invoicing API.
- Website performance: We added automated PageSpeed checks to all our websites and fixed the findings.
- Terms of Service and DPA: We have been working on a solid legal foundation for our SaaS offerings.
What’s next in November
#1, we are going to deploy the new architecture for our Virus and Malware Scan API (SaaS).
#2, we plan to ship a dashboard allowing customers of the Virus and Malware Scan API (SaaS) to manage their API keys and get insights into their usage.
#3, we will ship the new Terms of Service and DPA for our SaaS offerings.
