The plummeting cost of frontier intelligence George Cameron from Artificial Analysis opened the AI Engineer Melbourne 2026 conference with a stark data visualization of the current model landscape. Claims that AI progress has stalled are flatly contradicted by the release density of the last six months. We are seeing a structural shift where the "intelligence index"—a synthesis of multiple benchmarks—is climbing vertically while the cost to achieve those specific levels of reasoning is cratering. A year ago, achieving GPT-4 levels of performance was a luxury. Today, it is a commodity available for pennies. Cameron highlighted that Claude Opus 4.8 recently seized the intelligence mantle from GPT-5.5, but the real story lies in the "Pareto curve" of cost versus capability. Developers can now access Kimk 2.6 or DeepSeek V4 Pro at orders of magnitude lower costs than previous frontier models, often with only a three-to-nine-month lag in total intelligence. This democratization means that for most standard knowledge work tasks, high-end proprietary models are increasingly overkill. Why Notion switches default models every three weeks Sarah Sachs, Head of AI at Notion, argues that in this volatile market, optionality is the only real leverage a company has. Many startups are falling into the "lock-in trap," committing massive spend to a single provider like OpenAI or Anthropic in exchange for discounts. This is a strategic error. When a successor model is 40% more expensive but its predecessor is slated for deprecation in four months, a locked-in company is forced to eat the margin loss or hike prices on customers. Notion’s approach is to treat models as interchangeable components. They rotate their default model for users every few weeks based on a proprietary metric: cost per capability per second. Sachs noted that Claude Sonnet might consume significantly fewer tokens for the same task than a heavier model, making it the superior choice regardless of the sticker price per million tokens. Furthermore, she advocated for "outcome maxing" over "token maxing." Not every task needs an LLM; simple database field changes or email triaging can often be handled by CPUs or deterministic state machines, cutting token costs by up to 80%. Execution is a commodity and your IDE is dead Jeff Huntley delivered the most provocative segment, declaring that software development now costs less than minimum wage because coding has been fully commoditized. He pointed to PewDiePie, who is reportedly writing better property-based tests using AI tools than many career software engineers. This shift represents the destruction of the "knowledge gatekeeping" that defined the last two decades of tech. If a YouTuber can generate high-quality, deterministic system tests, the value of a developer is no longer in their ability to write syntax. This reality creates a "curiosity test" for the industry. Huntley observed that senior engineers who cannot explain the mechanics of an agentic loop—a simple `while true` loop that handles tool calls—are rapidly becoming obsolete. The IDE as we know it is a relic of a previous era; it is being replaced by cloud-based, agent-first workflows like Cursor and Claude Code. The message to the "Fortune 5 Million" is clear: transform your organizational chart to reflect a five-person team with AI-driven output, or face disruption from lean startups that have already done so. The architecture of agent memory versus context Igor Costa of AutoHand AI addressed the primary frustration of the current agent era: why do coding agents forget what they are doing after 15 messages? The industry has mistakenly treated "context window" as a synonym for "memory." While we have scaled context to millions of tokens, the agents still suffer from drift and collapse. To solve this, Costa's team is experimenting with "agent spawning"—an evolutionary approach where an agent reflects on a task, spins up a new version of itself with a specific subset of relevant memory, and carries forward only the necessary genetic traces of the previous session. This hierarchical reasoning model moves away from treating the LLM as a first-class citizen. Instead, the memory *is* the model. By using smaller, dense models (ranging from 20 million to 2 billion parameters) trained on specific customer data, companies can achieve higher correctness at a fraction of the cost. Costa emphasized that for long-horizon tasks, such as migrating the Linux Kernel to Rust, the agent must possess "episodic memory" that understands the dimension of time—something standard context-loading ignores. Why voice agents are abandoning Python for Rust Vamsi Ramakrishnan from Google Cloud closed the keynote by detailing the technical hurdles of Gemini Live. When scaling full-duplex voice agents for millions of users in India, the millisecond budget becomes the defining constraint. In a text-based chat, a 500ms delay is negligible; in a voice conversation, it is a catastrophic UX failure. The "hotpath" for these agents requires absolute determinism. While Python is the lingua franca of AI research, it is unsuitable for real-time voice orchestration at scale. Ramakrishnan revealed that his team moved to Rust to handle the state machines and regex patterns that manage conversation flow. By using regex to detect intent for regulatory compliance or simple repetitions, they bypass the need for an expensive, high-latency LLM call for every turn. This hybrid approach—using Rust for the deterministic loops and LLMs only for the generative elements—is the new blueprint for high-performance AI engineering. Conclusion The AI Engineer Melbourne keynote makes one thing certain: the era of simply "using an API" is over. The competitive edge has moved into the "harness"—the specialized software architecture that wraps these models. Whether it is Notion's multi-provider strategy, AutoHand's evolutionary memory, or Google's Rust-based low-latency loops, the winners are those who treat AI as a component within a larger, deterministic system. For individual developers, the directive is even simpler: pick up the guitar and learn how it works under the hood, or step aside for those who will.
Google Cloud
Companies
Apr 2022 • 1 videos
Steady coverage of Google Cloud. ArjanCodes contributed to 1 videos from 1 sources.
Aug 2024 • 2 videos
High activity month for Google Cloud. ArjanCodes among the most active voices, with 2 videos across 1 sources.
Feb 2026 • 2 videos
High activity month for Google Cloud. 20VC with Harry Stebbings and TechCrunch among the most active voices, with 2 videos across 2 sources.
Mar 2026 • 1 videos
Steady coverage of Google Cloud. Adam Savage’s Tested contributed to 1 videos from 1 sources.
Apr 2026 • 1 videos
Steady coverage of Google Cloud. TechCrunch contributed to 1 videos from 1 sources.
Jun 2026 • 1 videos
Steady coverage of Google Cloud. AI Engineer contributed to 1 videos from 1 sources.
- Jun 3, 2026
- Apr 22, 2026
- Mar 31, 2026
- Feb 23, 2026
- Feb 18, 2026
Overview of Rate Limiting and Throttling Rate limiting serves as a critical security and stability mechanism for modern APIs. At its core, it prevents a single client from overwhelming your server resources, whether intentionally through a **Brute Force attack** or accidentally via a misconfigured loop. In the context of API development, we often refer to this as **API throttling**—limiting the number of requests handled within a specific time window. Without these guards, your FastAPI application risks crashing under high load, leading to a degraded experience for all users. Prerequisites To follow this guide, you should have a solid grasp of **Python** and the FastAPI framework. Familiarity with HTTP request objects, decorators, and basic asynchronous programming is essential. Understanding how headers and IP addresses work within a network request will help you customize your limiting logic. Key Libraries & Tools - FastAPI: The high-performance web framework for building APIs. - SlowAPI: A library based on the Limits package designed specifically for FastAPI integration. - Zuplo: An API management platform and gateway that offers programmable rate limiting at the edge. - Redis: Often used as a backend for distributed rate limiting to sync request counts across multiple server instances. Code Walkthrough: Using SlowAPI While you can write a custom decorator to track IP addresses, using SlowAPI is the industry standard for Python developers. It provides a structured `Limiter` class and clean integration points. ```python from fastapi import FastAPI, Request from slowapi import Limiter, _rate_limit_exceeded_handler from slowapi.util import get_remote_address from slowapi.errors import RateLimitExceeded limiter = Limiter(key_func=get_remote_address) app = FastAPI() app.state.limiter = limiter app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) @app.get("/limited") @limiter.limit("5/minute") async def limited_endpoint(request: Request): return {"message": "This is rate-limited"} ``` In this snippet, we initialize the `Limiter` using `get_remote_address` to identify clients by their IP. The `@limiter.limit("5/minute")` decorator handles the logic: it checks the timestamp list for the client, determines if they've exceeded five hits in sixty seconds, and automatically raises a `429 Too Many Requests` error if they have. Syntax Notes A common pitfall is forgetting to include the `request: Request` argument in your path operation function. Even if your code doesn't use the request object directly, the `limiter` decorator requires it to extract client metadata. Additionally, SlowAPI uses a concise string syntax (e.g., "10/second", "100/day") which makes managing complex rules highly readable. Tips & Gotchas If you scale your API to multiple instances behind a load balancer, **In-Memory storage** for rate limits will fail. Each instance will have its own counter, allowing a user to bypass limits by hitting different servers. In production, always point your limiter to a shared Redis instance. Finally, consider **Burst Management**. A fixed window of 60 requests per minute might allow a user to fire all 60 in the first second. To prevent this, stack decorators to create a "10/second" burst limit alongside a "1000/hour" sustained limit.
Aug 23, 2024Overview of the Requests Library The Requests library stands as a monument in the Python ecosystem. It revolutionized how developers interact with HTTP by providing a human-readable interface over the complex and often clunky urllib3. For years, its motto, 'HTTP for Humans,' has guided its design, making it the de facto standard for sending API calls, scraping web content, and managing sessions. However, being an industry standard does not make a codebase immune to technical debt or questionable design patterns. By examining the internals of Requests, we gain insight into how a widely-used library manages cross-version compatibility, abstraction layers, and low-level networking. This walkthrough explores the core components—adapters, sessions, and models—while critiquing the architectural decisions through the lens of modern software engineering best practices. We will see how legacy requirements often conflict with clean code principles like the Single Responsibility Principle and Composition over Inheritance. Prerequisites To get the most out of this deep dive, you should have a solid grasp of the following: - **Python Proficiency**: Familiarity with classes, inheritance, and keyword arguments (`**kwargs`). - **HTTP Basics**: Understanding of methods (GET, POST), status codes, headers, and SSL/TLS verification. - **Design Patterns**: Awareness of the Adapter pattern and the concept of 'Mixins.' - **Testing Tools**: Basic knowledge of Pytest and the concept of mocking network requests. Key Libraries & Tools - Requests: The primary HTTP library for Python being reviewed. - urllib3: The low-level dependency that Requests wraps to handle connection pooling and thread safety. - Pytest: The testing framework used to validate the library's behavior. - charset-normalizer: A dependency used for character encoding detection. - Docker: A suggested tool for improving local and CI testing environments through containerization. Code Walkthrough: Adapters and Type Handling One of the most critical parts of the Requests architecture is the Transport Adapter. This layer allows the library to define how it communicates with different protocols. By default, Requests uses the `HTTPAdapter`, which relies on urllib3 to manage the actual socket connections. The Problem with Mixed Type Arguments In the `adapters.py` file, we encounter a pattern that often complicates maintenance: arguments that accept multiple types to perform different logical tasks. A prime example is the `verify` parameter. It can be a `bool` (to toggle SSL verification) or a `str` (providing a path to a CA bundle). ```python Current implementation pattern in Requests adapters def cert_verify(self, conn, url, verify, cert): if verify is False: # Disable SSL verification logic pass elif isinstance(verify, str): # Logic to load certificate from path pass ``` This design forces the method to perform 'type-switching' using `isinstance()` checks. While flexible for the user, it creates a brittle internal structure. A cleaner approach would involve splitting these into distinct parameters or using a more robust configuration object. This would allow the type system to catch errors at compile-time (or via static analysis) rather than relying on runtime checks. Refining Type Logic with Guard Clauses A better way to handle these scenarios is to separate the boolean toggle from the path configuration. By using guard clauses, we can flatten the nested logic and make the code more readable. For instance, if `verify` is false, we can exit the logic early, reducing the cognitive load for anyone reading the method. Architecture Critique: Mixins vs. Composition Requests makes heavy use of 'Mixins,' specifically the `SessionRedirectMixin`. In Python, a Mixin is a class that provides methods to other classes through multiple inheritance but is not intended to stand on its own. While popular in older Python frameworks, Mixins often lead to confusing 'spaghetti' inheritance where a superclass calls a method that is only defined in its subclass. The Session and Redirect Relationship The `Session` class inherits from `SessionRedirectMixin`. Looking at the source, the `SessionRedirectMixin` calls `self.send()`, yet the `send()` method is defined in the `Session` class itself. This circular dependency makes the code difficult to trace. It's nearly impossible to unit test the Mixin in isolation because it lacks the context of the class it is mixed into. Moving Toward Composition Modern software design favors composition over inheritance. Instead of making `Session` a child of a redirect class, we should treat 'redirect logic' as a tool that `Session` uses. By creating a standalone `RedirectHandler` and passing it to the session, we decouple the components. ```python class RedirectHandler: def resolve(self, response, session): # Logic lives here independently pass class Session: def __init__(self, redirect_handler=None): self.redirect_handler = redirect_handler or RedirectHandler() ``` This makes the code more modular. If you need to change how redirects work, you only touch the handler. If you want to test redirect logic, you don't need to instantiate a heavy `Session` object. Syntax Notes: Type Annotations and Compatibility You might notice that Requests often uses string literals for type hints, such as `"Response"` instead of just `Response`. This is a common practice in libraries that support older versions of Python or deal with circular imports. String annotations tell the interpreter to treat the type as a forward reference, preventing 'NameError' exceptions when a class hasn't been fully defined yet at the time of the type check. Furthermore, the library avoids modern features like `dataclasses` to maintain compatibility with legacy environments. While this makes the library incredibly stable and portable, it results in more boilerplate code in the `__init__` methods where every attribute must be manually assigned to `self`. Practical Examples: Custom Adapters The power of the Adapter design pattern is that you can extend Requests to support non-standard protocols. For example, if you wanted to add support for a 'mock' protocol for testing without hitting the network, you could subclass the `BaseAdapter`. ```python from requests.adapters import BaseAdapter from requests.models import Response class LocalFileAdapter(BaseAdapter): def send(self, request, **kwargs): response = Response() response.status_code = 200 # Logic to read a local file based on the URL response._content = b"Local content" return response Usage import requests s = requests.Session() s.mount('file://', LocalFileAdapter()) resp = s.get('file:///path/to/data.txt') ``` This demonstrates why the `BaseAdapter` exists, even if the current implementation of `HTTPAdapter` is a bit bloated. It provides the hook for developers to customize the transport layer entirely. Tips & Gotchas - **The 'is' vs '==' Trap**: In the Requests source, you'll see comparisons like `verify is False`. This is used because `True` and `False` are singleton objects in Python. Using `is` checks for identity, which is slightly faster than the equality check `==`, but it should be used carefully, as it won't work for generic values like strings or custom objects. - **Test Structure**: Always try to make your `tests/` directory mirror your `src/` directory. In Requests, some tests (like `test_requests.py`) have grown too large, covering multiple modules. Keeping a 1:1 mapping between source files and test files makes it significantly easier for new contributors to find where a specific feature is validated. - **CI/CD Automation**: For complex networking libraries, using Docker in your CI pipeline is a best practice. It allows you to spin up actual mock servers (like the `test_server` used in Requests) in a controlled environment, ensuring that your tests aren't failing due to local network flakes. - **Hierarchy of Exceptions**: When designing a library, create a base exception (e.g., `RequestException`) that all other custom errors inherit from. This allows users to write a single `except RequestException:` block to catch any error generated by your package.
Aug 16, 2024The Foundation of Modern Software Delivery Building a SaaS platform involves more than just writing functional code. If you ignore the underlying infrastructure and deployment strategy, you risk creating a system that cannot scale, breaks during updates, and ultimately drives customers away. To avoid these technical pitfalls, we look to the 12-factor app methodology. Developed by engineers at Heroku, these principles serve as the gold standard for cloud-native development. By implementing a specific subset of these practices, you can transform your deployment pipeline from a source of stress into a reliable, automated engine. Environment Isolation and Explicit Dependencies Your application should never rely on the implicit existence of system-wide packages. This is a recipe for the "it works on my machine" disaster. Instead, you must declare every dependency explicitly. In the Python world, tools like Poetry or pip manage these lists, while Docker provides the ultimate layer of isolation. By wrapping your app in a container, you specify the exact operating system and environment. This ensures that the code running on your laptop is identical to the code running in production. Separating Configuration from Code Hardcoding credentials or API keys is a major security risk. A robust SaaS architecture stores configuration in environment variables. This allows you to use the same code base across multiple deploys—staging, testing, and production—simply by swapping the environment settings. A quick litmus test for your setup: if you could open-source your entire code base tomorrow without leaking secrets, you've successfully separated configuration from logic. This practice also protects you from internal mishaps, such as an intern accidentally hitting a production database. Build, Release, and Run Deploying code requires a strict three-stage process. First, the **Build** stage transforms code into an executable bundle, like a Docker image. Second, the **Release** stage combines that bundle with the specific configuration for a target environment. Finally, the **Run** stage launches the application. You should never modify code in a running container. If you need a change, create a new release. This immutability makes it much easier to track the system's state and roll back if something goes wrong. Statelessness and Robustness To scale effectively, your application services must be stateless. Any data that needs to persist—user sessions, images, or database records—must live in stateful backing services like Amazon S3 or a managed database. When your app is stateless, you can kill, restart, or duplicate instances at will without losing data. Combine this with quick startup times and graceful shutdowns to ensure your system handles crashes or rapid scaling events without corrupting user data. Making Releases Boring The secret to stress-free engineering is making releases boring. High-performing teams achieve this by shipping many small updates rather than one massive "big bang" release. Use feature flags to hide new code until it's ready, and always verify changes in a staging environment that mirrors production data. Most importantly, stop making "tiny fixes" minutes before a launch. Lock your features, test thoroughly, and trust your pipeline.
Apr 1, 2022