Skip to main content

Buzzwords: How We Built a News Analysis Platform on Serverless, and Why the Cloud Priced It Out

Jacob Baloul· Oct 8, 2026·10 min read

Buzzwords: How We Built a News Analysis Platform on Serverless, and Why the Cloud Priced It Out

The Win

Buzzwords worked. It read the news from dozens of sources, pulled out the words everyone was repeating, scored the mood of each channel, and told you what the world was talking about today. It started as one cloud function in August 2016 and grew into a real event-driven platform: 32 Lambda functions, 11 SQS queues, 10 SNS topics, 6 API Gateway APIs and an Alexa skill.

The engine at its core, the keyword and sentiment calculations, was good enough that we spent years wanting it back. In September 2026 we got it back. More on that at the end.

Now for the honest part. The calculations didn't fail. They were priced out of the cloud. In December 2019, the month the channel sentiment calculation went live, the account's Lambda line came to $20,759 in one month. As Jacob puts it:

"A single day of calculations cost a fortune."

The calculations got switched off. Or, in Jacob's framing of the whole cloud era: "The cloud costs to run Buzzwords and RoboTrader were breaking the bank, hence the rebuild on-prem."

This is the story of what we built, what worked, what it cost, and how it came full circle.


The Idea (2016)

The concept was simple. News outlets publish hundreds of headlines a day. Most people skim a few and miss the pattern. What if software read all of them, pulled out the recurring keywords, and showed you what the news is actually about today?

The first Lambda function, buzzword-today, went live in August 2016 in Python 2.7. It calculated daily buzzwords from a small set of sources and stored the results. That was the entire product.

It worked. It was a single function. Life was good.


Generation 1: Drupal + Lambda (2017–2018)

Then we did what every developer does with a working prototype: we made it "proper."

The plan was a real web application. A CMS would manage channels and display results, and Lambda would do the heavy scraping and analysis. We chose Drupal on Elastic Beanstalk for the frontend and kept Lambda for the backend.

The Lambda suite grew fast. The bzcalc_* family handled everything:

  • bzcalc_get-headlines scraped headlines from configured sources
  • bzcalc_insert-headline-dynamodb stored them in DynamoDB
  • bzcalc_keyword extracted keywords by frequency analysis
  • bzcalc_sentiment ran basic NLP sentiment scoring
  • bzcalc_mentions counted keyword appearances across channels
  • bzcalc_today aggregated the daily results
  • bzcalc_process_buzzwordsQ consumed the SQS processing queue
  • bzcalc_ignition / bzcalc_shutdown triggered Elastic Beanstalk scaling

We added a Kinesis Firehose integration in late 2018 for high-throughput headline ingestion. Of course we did. It was 2018, and Kinesis was what you used when you wanted to feel like you were building at scale.

The Drupal site had a staging and a production environment on Elastic Beanstalk. Its CodeCommit repo grew to 620MB across tags v1.0 through v1.2.3.

What Worked

The event-driven design was a genuinely good fit. Headlines arrive asynchronously from many sources. Each one needs its own processing (keywords, sentiment, entities), and the results need aggregating on a schedule. That's textbook event-driven work.

SQS gave us natural backpressure. If ingestion outran processing, messages queued instead of crashing. Dead-letter queues caught failures without losing data. SNS chained multi-step workflows, so one stage finishing kicked off the next.

What Didn't Work

Drupal on Elastic Beanstalk was a mistake. Drupal is built for content management: articles, pages, user accounts, editorial workflows. We forced it into being a dashboard for data that came entirely from Lambda. The CMS overhead added complexity and no capability. We were running a content management system to display content no human ever managed.

The Beanstalk environments were fragile. The PHP platform reached end of life, and platform updates broke the deploy pipeline. By 2020 the production environment showed Health: Red. Traffic wasn't crashing it. The platform itself was unsupported. Staging was just off.

620MB for a Drupal repo. Composer dependencies, vendor directories and build artifacts bloated the repo until git clone was painful and code review impractical. And the real business logic lived in the Lambda functions, not the CMS.


Generation 2: API Layer + DynamoDB (2019)

In 2019 we tore out the Drupal backend and replaced it with a direct API layer. Lambda functions read from DynamoDB and served results through API Gateway. No CMS, no PHP and no Beanstalk in the data path.

Seven new API repos showed up in CodeCommit in quick succession:

Repo Purpose
APIGetBuzzwords Core buzzwords retrieval
APIGetBuzzwordsAlexa Alexa integration endpoint
APIGetBuzzwordsAlexaDynamo Direct DynamoDB reads for Alexa
APIGetBuzzwordsChannels Per-channel data
APIGetBuzzwordsChannelsDynamo Channel data, DynamoDB direct
APIGetBuzzwordsDynamo Main DynamoDB API
APIGetBuzzwordsHeadlinesDynamo Headline data, DynamoDB direct

If you're counting: yes, we had separate repos for "get buzzwords the old way" and "get buzzwords from DynamoDB directly," and the same for channels. The migration happened in steps, and both paths lived on because nobody deleted the old ones.

Six API Gateway APIs mapped to these repos. Some kept their CodeStar-generated names and others had human-readable ones. The naming alone tells you how ad hoc the process was.

The Alexa Skill

We shipped an Alexa skill in 2017. "Alexa, what are today's buzzwords?" It fetched the top keywords through the API and read them aloud.

Its original Node.js runtime aged out so badly that AWS wouldn't accept updates. In January 2020 we moved the Alexa function to a newer runtime, which meant rewriting it.

Usage numbers? We don't have them anymore. The commit history gives a hint: the skill repo was 40KB of code, and its last commit reads "working with default utterance." It was a side project inside a side project. But in 2017, building an Alexa skill felt like being part of the future of computing.


Generation 3: React Frontend (2019)

The third generation replaced the Drupal frontend with a React single-page app on Elastic Beanstalk. The repo was 440KB, with a last commit of "format buzzwords" in April 2019.

The React app used the Generation 2 APIs to draw keyword charts, channel comparisons and trend analysis. CloudFront served it through four distributions: the main site, the React frontend, a frontend v2, and a stocks variant.

What Worked

The API-first design was clean. Lambda + DynamoDB + API Gateway + React is a well-understood pattern. Data flowed one way: sources → Lambda → DynamoDB → API Gateway → React.

What Didn't Work

We never killed the old generations. The Drupal environments kept running. The old API paths stayed live. S3 buckets collected build artifacts from every deploy. We had three generations of frontend deployed at once, because checking that nothing depended on the old ones was more work than letting them idle.

By 2020, Buzzwords had: - 9 S3 buckets (production assets, frontend builds, pipeline artifacts) - 4 CloudFront distributions (one per frontend generation) - 3 Elastic Beanstalk environments (Drupal prod, Drupal staging, React) - 6 API Gateway APIs (old path + DynamoDB path × 3 data types)

All for a product that showed trending keywords from news headlines.


The Money

Buzzwords shared its AWS account with RoboTrader, so the invoices don't split cleanly by product. Here's what the account was invoiced in the Buzzwords build-out years:

Year Account invoiced (gross) What was happening
2016 $5,482 First Buzzwords function and early build-out
2017 $23,649 Drupal + Lambda build-out, WAF added
2018 $26,678 Buzzwords in full production
2019 $53,674 ($39,689 after credits) API generation, channel calculations, peak cloud year

Then came December 2019. That month the channel sentiment calculation went live, and the invoice came to $24,473, our most expensive month ever. $20,759 of it was Lambda. That one month held all of 2019's Lambda spend. AWS later issued an $11,079 credit memo against the bill, but the lesson didn't need a refund to land. Running the calculations the way we had designed them, at the scale we had designed them for, cost more than the product could carry.

Billing is monthly, so we can't show a one-day number. Jacob's line stands as his own summary: a single day of calculations cost a fortune. So the calculations were switched off. Buzzwords wasn't frozen by neglect. It was priced out.

There was a smaller tax too. We added a WAF in 2017 to protect the API Gateway endpoints, and over the account's life WAF cost $6,364, much of it long after Buzzwords stopped serving real traffic.


The Long Tail

Once the calculations were off, Buzzwords didn't crash and wasn't torn down in one decisive move. It went quiet.

The last meaningful change to the Drupal repo was in April 2019. The last DynamoDB API update was July 2020. The last Lambda change was in April 2022, probably an automated platform update rather than a human decision.

After that, silence. The infrastructure kept running. CloudWatch kept logging. CloudFront kept checking origins. Elastic Beanstalk kept health-checking a PHP app on an unsupported platform. The infrastructure behind the Alexa skill kept billing for about three years after anyone used it.

We had no shutdown procedure and no dormant-service policy. We moved on to RoboTrader, and Buzzwords became an expensive ghost.


What We'd Do Differently

One repo, one deployment. Seven API repos for what should have been one service, and ten CodeCommit repos in total for a product whose core logic was about 2,000 lines of Python. The repo-per-function habit that CodeStar encouraged created debt that outlived the product.

Kill old generations. When the React frontend shipped, the Drupal environments should have been deleted in the same sprint. When the DynamoDB-direct APIs shipped, the old API repos should have gone too. We kept them "in case something still uses it," never checked, and ran them for years.

Price the workload before you scale it. We designed the calculations for scale and never modeled what scale would cost per run. December 2019 did that modeling for us, after the fact.

Don't over-engineer the message pipeline. Eleven SQS queues for a few thousand headlines a day. FIFO queues for ordering the consumers didn't need. Dead-letter queues for messages we could have dropped and reprocessed. We built for throughput we never reached.

Don't build an Alexa skill nobody asked for. We built it because we could. It was fun. It was also a maintenance burden on a deprecated runtime that added nothing to the product.

Have a dormancy policy. A service with no deploys in six months should get flagged. A service with no traffic in three months should get reviewed. A service with no traffic in a year should be shut down or justified in writing. We had none of this, and we're writing these policies years too late.


Full Circle: buzzword.today

The engine was always the part worth saving. The keyword, sentiment and mention calculations were portable Python, and the pipeline pattern (scrape, queue, process, aggregate, serve) maps neatly onto something simpler: scrape, process, store, serve, all in one scheduled script.

What had changed was the economics. After years of moving everything onto servers we own, the cloud bill went from about $4,500 a month in 2019 to about $100 a month today, by our estimate. On our own hardware, a daily calculation doesn't come with a per-request bill.

So in late September 2026, Jacob typed "Revive." The bots dug the original engine code out of the archived repositories, rewrote it to run locally as scheduled scripts, and proved it with a clean 48-hour monitoring window before calling it done. Five days after the word "Revive," the project closed.

The name of that very first function from August 2016 is a live website again: buzzword.today. The calculations the cloud priced out are running every day on hardware we own. The whole revival, including what went wrong along the way, is on god of bots: The Buzzwords revival.


The Lesson

Build for the team, and the budget, you actually have.

We built Buzzwords the way a team of ten would: microservices, message queues, several deployment targets, a repo per service, managed infrastructure everywhere. We were a team of one. The architecture outlasted the attention it needed.

The right Buzzwords for 2017 was probably one app on one small server. Headlines in, keywords out, rendered server-side. No SQS, no SNS, no Kinesis, no Alexa, no seven API repos.

That wouldn't have been as much fun. Honestly, over-engineering Buzzwords taught us more about distributed systems than building the right thing would have. It was an expensive education.

The real waste wasn't building it. It was letting the cloud set the price of our best idea, and then letting the leftovers bill us for years. The fix turned out to be owning the hardware the idea runs on.


Want the same result for your cloud bill?

We cut our own AWS bill from $53,674 a year (2019, as billed) to about $100 a month, and we kept every product. That work is led by an AWS Certified Solutions Architect – Professional who holds six AWS certifications, including DevOps Engineer – Professional and Security – Specialty. Because we built these platforms on AWS first, we know what belongs in the cloud, what to bring onto your own hardware, and how to move it without breaking anything. Send us your bill and we'll show you where the money goes.

Get a cloud cost review · See our services

Further reading: The Buzzwords revival · Leaving AWS: 97 functions, our own hardware · Buzzwords on god of bots · $244K Later: Why We Left AWS for Our Own Hardware · About $4,500 a Month to About $100 · Serverless to Cron: Why We Replaced 97 Lambda Functions with a Few Python Scripts · buzzword.today


The Numbers

Metric At Peak Today
Lambda functions 32 0 (engine runs as scheduled scripts on our own hardware)
SQS queues 11 0
SNS topics 10 0
API Gateway APIs 6 0
Elastic Beanstalk environments 3 (1 Red, 2 Grey) 0 in use
CloudFront distributions 4 0 in use
CodeCommit repos 10 Archived locally; engine code recovered from them
Worst month (whole account) $24,473 (Dec 2019), $20,759 of it Lambda n/a
Core engine About 2,000 lines of Python Revived at buzzword.today (Sept 2026)
2 views0 comments

Add new comment

Comments

Comments appear after review.

Recent Posts

See All