I Argued With an AI for 20 Minutes About Async Code — And I'm Surprisingly Happy

ByEdward F. Wahl

Published Mon Jun 01 2026

If you have ever spent twenty minutes debating an obscure AWS Lambda invocation pattern with an AI, you might question your life choices. But here I am: amused by the wasted time but ultimately happy with the outcome and understanding I gained.

Let's rewind.

I was refining some Python code for a Lambda function. My goal was straightforward: apply internal coding standards properly — minimal comments, clear docstrings, manageable complexity — nothing wild. The AI handled it well, refining my code with consistency.

But things went sideways when we reached a particular function named _invoke_webhook_sender. The innocent-looking function asynchronously invokes another Lambda, send_result_to_webhook. In theory, straightforward enough:

  • Invoke send_result_to_webhook asynchronously.
  • Let the downstream Lambda handle retries, failures, and all the messy reality of hitting an external webhook.

Simple, right? Well, not so fast. Asynchronous programming often feels deceptively straightforward, but it's notoriously subtle and complex for developers. Its inherent complexity stems from concurrency, race conditions, and error handling intricacies — situations where timing and order aren't guaranteed. LLMs struggle particularly with this because their expertise is fundamentally pattern-driven, relying heavily on recognizing familiar structures. When nuances or edge cases arise that aren't widely represented in their training data, such as subtle failures in asynchronous handoffs, they can miss critical details.

Enter the Rabbit Hole

The AI, ever helpful, confidently suggested logging any invocation failures, but then quietly swallowing the exceptions. "Best practice!" it cheerfully asserted. After all, async invocation means you don't need to wait around. Fire and forget.

But here's the rub: what if the "fire" part itself never actually happens? What if AWS rejects your call outright — wrong permissions, malformed request, throttling? In that scenario, the downstream Lambda never even gets invoked. Its dead-letter queue (DLQ) remains empty. Your upstream DLQ doesn't notice, because technically your handler succeeded (it swallowed the exception, remember?). Suddenly, you've got a silent failure on your hands.

Thus Began My 20-Minute Debate

"This isn't right," I told the AI.

"It adheres to serverless best practices," it replied calmly.

"But it can fail silently!"

"Decoupling is generally beneficial."

"Decoupling doesn't mean ignoring failures," I insisted.

"You should have a DLQ downstream."

"But the invocation itself can fail — then the downstream DLQ is useless!"

After several rounds of politely helpful but increasingly unproductive exchanges, I realized something critical: the LLM was logically consistent and yet stuck in a completely wrong pattern it was unable recover from. It followed best practice guidelines blindly but could not understand the real context of passing off an asynchronous action.

Why AI Needs Humans (Still)

Current Large Language Models (LLMs) — or "AI" if you prefer — demonstrate a powerful ability to discern and replicate intricate statistical patterns from vast datasets. They are becoming adept at tasks like enforcing coding standards by identifying deviations from common practices, suggesting code completions aligned with established styles, and refactoring code based on learned optimal solutions.

However, they don't (and, in their current architectural paradigm, likely will not ever) possess true "developer understanding" of a codebase. This understanding isn't mystical; it's a complex amalgamation of hard-earned experiential knowledge, nuanced contextual understanding, and an appreciation for the tangible consequences of system behavior, including the understanding that two correctly-constructed lambdas can combine to silently drop important notifications.

Did I Waste 20 Minutes of My Life?

In the short term, yes. Once I realized the problem, I could have fixed it quickly myself and didn't really benefit from trying to "explain" the problem to an LLM.

In the larger scope, though, I don't think this was a waste. Agentic coding is a new tool for developers, and this helped me understand how to use the tool effectively and recognize its limitations. In the future, I expect to produce better quality, more efficient code with the help of an agentic coding agent. This experiment helped transform my theoretical understanding of how an LLM works into practical experience of how to more effectively integrate agentic coding into my workflow.

Working Strategically: Coding Using Agentic AI Tools

The hype/fear around AI is loud: "Create software without developers!" "AI's taking our jobs!" A recent NPR article quotes a tech leader predicting radical change: "Instead of having coding assistance, we're going to have actual AI coders and then an AI project manager, an AI designer and, over time, an AI manager of all of this. And we're going to have swarms of these things."

I see things differently. Agentic coding tools streamline our workflow, letting us skip mundane tasks. But AI still lacks that intuitive leap of understanding and ability to work through chains of logic cultivated through years of tackling complex systems and subtle bugs.

Scaling current LLMs with more computational power won't magically enable chains of AI agents to operate fully autonomously without human oversight. Looking at how LLM technology actually works, such a leap will require fundamental advancements in AI technology, not just more compute.

AI isn't replacing me anytime soon. Instead, it's becoming part of my coding toolkit, allowing me to focus on deeper architectural challenges where human insight really shines. That's the part of development I enjoy most — and it's a future I'm genuinely looking forward to.

Previous

A Primer on Apple's App Tracking Transparency
If an app tracks user activity, Apple requires them to declare all information they collect as well as whether that data is linked or tracked. This includes collection by the app itself and any third parties the app uses. The app owner is responsible for knowing and correctly reporting privacy information for all components in the app.