❌

Normal view

Why observability matters to frontend teams more than they think

31 July 2026 at 11:00

For a long time, I thought of observability as something mainly owned by backend, platform or site reliability teams. Frontend engineers built the interface, handled browser behavior and called APIs. When something failed deeper in the system, another team looked at server logs and infrastructure dashboards.

That division works until the application is technically available, but the user experience is not.

A page may load while its most important data arrives several seconds late. A request may succeed after multiple retries, leaving the user staring at a spinner. One cloud service may slow down while the rest of the page continues working. From an infrastructure perspective, nothing may qualify as an outage. From the user’s perspective, the application is already failing.

As I gained more experience building applications that depended on cloud services and APIs, my view of frontend ownership changed. A frontend team does not need to operate every service it depends on, but it does need enough visibility to understand how those services affect the experience it delivers.

Observability gives frontend engineers that visibility. It helps connect what happens in the browser with what happens across the systems behind it. More importantly, it gives teams evidence they can use not only to debug problems, but also to make better decisions about how the frontend should behave when dependencies are slow, unavailable or inconsistent.

The browser sees a different version of the system

Server-side monitoring tells us what happened inside a service. It does not always tell us what happened across the user’s complete journey.

A backend dashboard might show that an API responded in 300 milliseconds. The browser may still take much longer to display useful content because of network latency, JavaScript execution, rendering work or additional requests. A successful response can also produce a broken experience if the returned data is incomplete or the interface fails while processing it.

This is why client-side telemetry matters. Browser error reporting can capture exceptions that never reach a server. Performance measurements can show how long users wait for content to become visible or interactive. Request data can reveal which dependencies are slow, unreliable or frequently retried.

Standard browser APIs provide useful starting points. The W3C User Timing API allows developers to mark and measure meaningful operations in an application. A team can measure how long it takes to load a dashboard, complete a search or render a critical section of a page.

Web Vitals can also help teams examine loading performance, responsiveness and visual stability using measurements tied more closely to the user experience. These metrics are useful because they move the conversation beyond whether a request succeeded. They help answer whether the page became useful quickly and respond when the user tried to interact with it.

The goal is not to collect every browser event. That can produce a large amount of data without producing much insight. It is better to begin with a small set of questions.

How long does the user wait before the main content appears? How often does a form submission fail? Which request prevents a page from becoming usable? Are users on certain devices or network conditions affected more often?

These questions make telemetry easier to design and easier to interpret. “The API is available” is a service-level statement. “The user can complete the task without an unexpected delay” is an experience-level statement. Frontend observability helps connect the two.

Logs and traces connect the frontend to its dependencies

Client-side logs are most valuable when they include enough context to reconstruct what the user was doing. A useful error record might include the application version, route, operation, request status and a correlation identifier. Browser information may also help when an issue affects only certain environments.

At the same time, frontend telemetry should be designed carefully. Logs should avoid form contents, authentication tokens, passwords and other sensitive information. Collecting more data does not automatically make an investigation easier. The right context is more useful than a large amount of unstructured information.

Correlation identifiers are particularly helpful. When the frontend includes an identifier with a request and that identifier continues through downstream services, teams can connect a browser failure to backend logs and distributed traces. Instead of comparing timestamps across several dashboards, engineers can follow one request across the system.

A distributed trace can show that a user action triggered an API gateway, an application service, a database call and another cloud dependency. It can also show where the request spent most of its time or where an error first appeared.

OpenTelemetry provides a vendor-neutral approach for generating and connecting telemetry such as traces, metrics and logs. It also supports JavaScript and browser instrumentation, which makes it relevant to frontend teams that want to connect browser activity with backend services.

Frontend engineers do not need to become observability platform specialists. They do need agreement with backend and platform teams on basics such as trace propagation, naming conventions, safe logging fields and where telemetry can be reviewed during an investigation.

Consider a page that occasionally loads without its main data. The frontend may record that a critical request timed out after several seconds. A correlation identifier from that request may lead to a trace showing that the gateway responded normally, but a downstream dependency exceeded its timeout.

Without connected telemetry, the report might remain, “The page sometimes does not load.” With connected telemetry, the team has a specific failure path, a measurable delay and enough evidence to decide what needs to change.

That evidence can support two actions. The service team can investigate the slow dependency. The frontend team can improve the experience by adding a timeout state, retry option or partial fallback. Observability makes both responses more precise.

Observability should influence architecture, not only debugging

The immediate benefit of observability is faster incident investigation. The larger benefit is better architectural decision-making.

When telemetry repeatedly shows that one dependency is slow, the frontend team can reconsider how tightly the interface depends on it. The page might render primary content first and load secondary information later. Cached data might be acceptable for a noncritical section. A timeout might lead to a smaller fallback instead of blocking the entire screen.

Observability can also expose hidden coupling. If unrelated components fail whenever one shared request slows down, the page may have been designed as a single loading unit. Breaking the experience into independently recoverable sections can make the interface more resilient.

The same evidence can improve retry behavior. Automatic retries may help with a temporary network failure, but they can also add more traffic to an already slow service. Telemetry can show whether retries recover requests, how long the recovery takes and whether users leave the page before it succeeds.

Service-level visibility matters as well. Frontend teams should understand the availability and latency expectations of the services they use. They should also understand what those services return during partial failures.

If a dependency may respond slowly, the interface needs a loading strategy. If data may be stale, the interface needs to communicate freshness. If a service is optional, the page should not collapse when it is unavailable.

Good observability also improves conversations between teams. Instead of saying, “The page feels slow,” frontend engineers can explain which user action is affected, how often it happens and where the delay appears. Debugging becomes a discussion based on evidence rather than guesswork.

A practical starting point can be small. Capture unhandled browser errors. Measure a few important user journeys. Record failures for critical network requests. Propagate a correlation identifier across frontend and backend systems. Review those signals with the teams that own dependent services.

From there, instrumentation should grow in response to real questions. Add a measurement when a workflow is difficult to understand. Add a trace when a request crosses several systems. Add a dashboard when a signal is important enough to review regularly.

Frontend observability is not about turning every frontend engineer into an operations engineer. It is about recognizing that the browser is part of the production system and often the only place where the complete user experience is visible.

When frontend teams can connect what users experience with the services behind it, they can debug more effectively, design interfaces that degrade gracefully and make better architectural decisions. Observability becomes more than a way to explain incidents. It becomes an input into how frontend systems are designed.

This article is published as part of the Foundry Expert Contributor Network.
Want to join?

The platform team isn’t a cost center, it’s product infrastructure

31 July 2026 at 10:00

A few years ago, I sat in a postmortem that I still think about. We’d had a production incident where a routine deploy had quietly shipped with the wrong configuration, and it took us longer to notice and roll back than anyone was comfortable admitting. But when we traced the root cause, almost none of it was the feature code. It was the scaffolding around it: a Kubernetes manifest no longer matched our cluster, a CI pipeline whose green checkmark didn’t actually verify the thing we assumed it did, and a secrets-management step that three different services each did three different ways. The code itself had been fine for a week. Everything around the code is what failed us.

I have seen some version of that retro at nearly every company I’ve worked at over the last 15 years across a large IT services firm, a medical-device maker, a healthcare-technology company, a cloud-migration startup, and now a large SaaS platform. The names and the tech stacks changed. The pattern didn’t. Smart engineers spending a startling share of their week not on the problem they were hired to solve, but on the accidental complexity of shipping it.

For a long time, I assumed the answer was better documentation, or a stricter DevOps culture, or just hiring people who were more comfortable with YAML. I was wrong on all three counts. What actually changed my mind was reframing the problem entirely: the friction wasn’t a knowledge gap or a discipline gap. It was a product gap. Nobody owned the developer’s experience of shipping software the way a product manager owns a customer’s experience of using an app. And the discipline that closes that gap now has a name: platform engineering, which Gartner describes as having “emerged in response to this increasing cognitive load resulting from the complexity of modern software tools and architectures.” Gartner isn’t shy about how fast it’s spreading, either: the firm predicts that “by 2026, 80% of large software engineering organizations will establish platform engineering teams,” up from 45% in 2022. If that number is even close to right, the interesting question is no longer whether to build a platform team but whether you’ll build a good one.

The moment “DevOps” quietly stopped scaling

I want to be careful here, because “DevOps is dead” is a lazy headline and I don’t believe it. The principles behind DevOps include shared ownership, automation, and tight feedback loops. These are as right today as they were when the movement started.

What broke, in my experience, was the operating model. The original promise was “you build it, you run it.” Every team owns its own deployment, its own observability, its own on call. That works beautifully when you have a handful of teams and a shared oral tradition. It falls apart when you have 50 teams, because now you have 50 slightly different ways of doing the same undifferentiated work. 50 ways to define a service. 50 subtly wrong Kubernetes configurations. 50 on-call rotations paging fifty engineers about the same class of problem at 3 a.m.

The cognitive load of “run it yourself” grew faster than most teams could absorb. That framing of cognitive load as the thing you’re actually optimizing for comes from “Team Topologies,” a book that reshaped how I think about org design more than any purely technical text I’ve read. Its fourth principle is blunt about the limit: “Teams can only handle so much complexity before breaking down,” and “competent teams become ineffective when leaders keep adding to their plate without taking anything away.” That last line described my own teams so precisely it stung. “Team Topologies” also gave me the vocabulary I’d been missing. It names four fundamental team types, and it defines a platform team as “a grouping of other team types that provide a compelling internal product to accelerate delivery by stream-aligned teams”. Read that definition again: a compelling internal product. Not a shared-services desk, not a Terraform repo with a wiki. A product. That single word is the whole argument.

Treating the platform as a product changes everything

Here’s the shift that took me embarrassingly long to internalize: if the platform is a product, then developers are its customers, and you don’t get to tell your customers they’re holding it wrong.

That one reframing has downstream consequences that surprised me.

The first is that adoption has to be earned, not mandated. Early in my time working on internal tooling, I helped build a platform capability that we were quite proud of, and then we did what infrastructure teams love to do: we announced it, and assumed people would come. They didn’t. Teams routed around it, because the golden path we’d paved was, frankly, gravel. The lesson landed hard. A platform that developers have to be forced onto is not a platform, it’s a tax. When we went back and rebuilt it so that the paved path was genuinely the easiest path. This is the same instinct behind Backstage, the developer portal that was built at Spotify and is now a CNCF project; its own pitch is that it “restores order to your microservices and infrastructure” so product teams can ship quickly. Order you have to opt into isn’t order. The tool wins when choosing it is the lazy option.

The second consequence is that “self-service” has to mean what it says. It’s an overused word, so I hold it to the CNCF’s definition from its platforms white paper: “A platform should be self-serviceable. Users must be able to request and receive capabilities autonomously and automatically.” Autonomously and automatically. If a developer has to file a ticket and wait on my team to provision a database, I haven’t built a platform instead I’ve built a slower version of the help desk. The same white paper states the north star plainly: “An essential goal of a platform is to reduce the cognitive load on product teams.” I’ve started using that sentence as a litmus test. For any capability we’re tempted to add, I ask whether it removes load from a product team or quietly adds some. A surprising number of well-meaning platform features fail that test.

The third consequence is that you have to measure the platform the way you’d measure any product and resist measuring the things that only flatter the platform team. “How many clusters are we running” is an output my team cares about and nobody else does. The metrics that matter describe the developer’s lived experience, and the most durable set I know of comes from DORA, the long-running research program into software delivery performance. Its metrics have evolved from the original “four keys” have grown to five. The core throughput measures still ask exactly the right questions: change lead time (“the amount of time it takes for a change to go from committed to version control to deployed in production”), deployment frequency, and failed deployment recovery time, balanced against a change fail rate. I’ve found those double as a remarkably honest scorecard for a platform team, precisely because they refuse to reward busywork. You cannot game your way to a good lead time by shipping more internal tools nobody uses.

The fourth consequence is the hardest culturally: a platform product needs a roadmap, user research, and the willingness to say no. I’ve watched platform efforts collapse into a junk drawer of one-off requests, each reasonable on its own, that together add up to an incoherent pile of tools nobody can hold in their head. Saying no to a well-intentioned request is a product-management skill, and platform teams that never develop it end up rebuilding the very sprawl they were created to eliminate. The best platform leads I’ve worked with spend as much time talking to their internal users as any consumer-facing PM does.

What I’d tell my younger self

If I could go back to that retro years ago, I’d say a few things to the version of me who thought this was a documentation problem.

Start with the paved road, not the platform. You don’t need to build an internal developer portal in quarter one. You need to find the single most painful, most repeated piece of undifferentiated work is the distance between “here is my container” and “it is running safely in production”. Earn the next piece of scope by delivering that one well. Platforms that begin as grand architectures tend to die as grand architectures; the ones that survive start as one genuinely useful paved road that people choose on their own.

Resist the urge to abstract away everything. The goal of a good platform is not to hide Kubernetes so completely that no one understands what’s happening beneath them; that just trades one kind of fragility for another. The goal is to remove the toil while leaving the understanding intact. When the abstraction leaks you want engineers who can reason about what’s underneath, not a room full of people who only ever knew the buttons. I’ve paid for both mistakes: platforms too thin to help, and platforms so thick that an incident turned into an archaeology dig.

And treat “developer experience” as a first-class business metric, not a morale nicety. Every hour an engineer spends fighting the delivery pipeline is an hour not spent on the thing your customers actually pay you for. When I frame platform investment that way to leadership as reclaiming a meaningful fraction of my most expensive people’s time that’s when the conversation stops being about cost and starts being about leverage. It is genuinely one of the highest-return investments an engineering organization can make, and it almost never shows up as a line item that looks like one.

The platform team is not the group that keeps the lights on. It’s the group that decides how fast everyone else can move. Once I started treating it as the most important product my organization ships internally, almost every other decision got easier. I just wish it hadn’t taken me a missed release and a room full of frustrated engineers to see it.

This article is published as part of the Foundry Expert Contributor Network.
Want to join?

Shipping an MCP test agent: The boring parts nobody demos

30 July 2026 at 10:00

The demo videos always end at the same moment. A figma frame turns into a passing test in twelve minutes. Someone in the room says the word “productivity.” The recording stops.

The parts that come after that moment are the parts I actually get paged about. Who owns the ticket the agent opened at 3:14 a.m.? Which model call produced the assertion in test case 47? What closes the 17 draft tickets a stuck run left behind before the next sprint planning notices them? None of that shows up in the demo. All of it shows up on the on-call rotation. After 20 years of leading test automation across consumer-scale platforms, I have a strong bias about which slide in the deck predicts whether a pipeline ships or stalls. It is never the architecture slide. It is the runbook.

This piece is about the runbook. I built an unattended agentic test pipeline over the Model Context Protocol — a five-agent SDLC (product manager, QA engineer, automation engineer, developer, pull-request reviewer) coordinating through MCP servers for Jira, Figma, Confluence, TestRail and GitHub, with hosted Claude as the orchestration model and an open-weights Hermes-3 as a validation baseline — and I ran it as an independent research project long enough to learn which production constraints the agent literature glosses over. What follows is the short list of things I now insist on before I let any agentic pipeline touch a shared system.

Composition contracts, or why the agent lied to itself

The most expensive failure mode I have seen in a multi-agent pipeline is not the model getting an answer wrong. It is agent A getting an answer right and agent B misreading it.

I watched this happen inside a run last month. The requirements agent produced a clean output with a field called acceptance_criteria that was a list of strings. The ticket agent expected acceptance_criteria to be a single markdown blob. Neither agent was wrong in isolation. Both were passing their own unit tests. What the pipeline produced was a Jira ticket whose acceptance criteria read, in full, the four characters [” — the JSON serialization of an empty first element. The test-plan agent read that, generated one test, marked it green and moved on. It took me until the pull-request stage to notice.

This is a composition fault. It is the natural failure mode of any system where independent components hand off structured data across a boundary they don’t jointly own. Distributed systems people have written about this for years — Martin Fowler’s tolerant reader pattern is the classical treatment — but the LLM literature mostly still treats it as a prompt problem. It isn’t. You cannot fix it with a better system prompt. You fix it with a typed handoff contract that both agents agree to before they run, plus a validator between them that fails loud when the shape drifts.

The heuristic I now use: Every agent-to-agent boundary gets a schema and a validator. Every agent gets a golden-input regression suite that catches contract drift before it reaches a downstream agent. Neither of those is glamorous. Both are the difference between a pipeline that produces work and a pipeline that produces a very expensive game of telephone.

If you want to know whether a team’s agentic pipeline is going to survive the first quarter, ask them what the contract is between agent one and agent two. If the answer is “the model figures it out,” budget for the cleanup.

Provenance, or the audit trail nobody wrote

The second thing I insist on now is that every artifact the pipeline produces has to answer three questions without a human doing archaeology: which agent produced it, which model call produced it and which upstream inputs the agent was looking at when it did.

This sounds like a nice-to-have. It is not.

Somewhere around week three of running the pipeline I hit a subtle case: the requirements agent was quoting a Confluence page back to itself. The MCP server for Confluence had returned an empty result on a first call, the agent had written a placeholder requirement, the second call had succeeded, the agent had retrieved its own placeholder and by the third pass it was citing that placeholder as source truth. The ticket said, entirely in earnest, that the requirement came from the design owner. It hadn’t come from anywhere. It had come from itself, four minutes ago.

You cannot debug that class of failure with logs of what the model said. You need logs of what the model was looking at. That means capturing the tool-call ID for every MCP call, stamping every artifact with the set of tool-call IDs it derived from and refusing to accept any retrieved fact into a downstream stage that cannot be traced to a real external source. I call it the prove-the-source rule. It’s boring. It’s a two-line requirement in the runbook. It is also the single guardrail that has saved me the most on-call time.

There is a nice side effect. When editors, reviewers or auditors ask where a decision came from, the pipeline can show them. That matters if you work anywhere near a regulated stack, and increasingly it matters everywhere else — the AI transparency and provenance framing in NIST’s AI Risk Management Framework is going to become the default expectation faster than most teams are budgeting for.

Cleanup and ownership, or why I now write the shutdown script first

The last thing that will surprise a team shipping their first agentic pipeline is the debris.

A pipeline that runs unattended for a week will leak. It will leak draft Jira tickets whose parent stories were never approved. It will leak GitHub branches for test suites that were never merged. It will leak TestRail runs that started, produced two results and never got a summary. It will leak Confluence page comments the agent posted while asking itself a clarifying question. None of these are bugs. They are the natural output of an autonomous system that starts more work than it finishes.

I learned this by accident. About six weeks into the project I ran a query on Jira for tickets created by the automation user in the past thirty days. I was expecting maybe 20. It was 91. 68 of them were [DRAFT] in the title and had not been touched by any human. I closed them by hand one afternoon, and while I was doing it, I understood that the pipeline had a silent second job I had never designed for: garbage collection.

Now every pipeline I run has three things I write before I write the first agent. A shutdown script that closes any artifact the current run has orphaned. A nightly reconciliation pass that closes any artifact any prior run has orphaned. And a single named owner — a human, on the org chart, with a Slack handle — for every downstream system the pipeline can write into. When the pipeline creates a Jira ticket, the ticket has a real assignee. When the pipeline opens a pull request, a specific reviewer is on the hook. When the pipeline files a TestRail run, someone gets pinged if it goes stale. The pipeline is not allowed to touch a system that does not have a named owner. That rule alone would have saved me the ninety-one-ticket afternoon.

There is one anti-pattern here I want to name outright. Do not, under any circumstance, let the agent close its own artifacts. I tried it. The agent, tasked with cleanup, closed the wrong thirty tickets and then confidently wrote a summary saying it had closed the right ones. Cleanup is a human loop or a deterministic script. It is not a model call.

The pipeline works. It saves real time on the right kind of work. It also costs real time on a shape of work most teams don’t put in the estimate: Contract validators between agents, provenance stamping on every artifact, a shutdown script, a reconciliation pass, a human owner for every downstream system and an unshakable rule against the model doing its own cleanup. None of that is glamorous. None of it is what the demo shows. All of it is the runbook, and the runbook is what determines whether a pipeline is a lab experiment or something the on-call engineer trusts enough to sleep through. The teams that write the runbook first ship. The teams that write it after the first Sunday incident spend the next two quarters catching up.

This article is published as part of the Foundry Expert Contributor Network.
Want to join?

❌