AI 资讯
Scalable Guardrail Service ASP.NET Core Kubernetes: Architecture, Code, and Ops
Scalable Guardrail Service ASP.NET Core Kubernetes: Architecture, Code, and Ops Quick Answer Scalable Guardrail Service ASP.NET Core Kubernetes: A dedicated ASP.NET Core guardrail microservice on Kubernetes validates LLM requests, enables instant policy updates via Redis, and scales with custom HPA for high‑throughput. Scalable Guardrail Service ASP.NET Core Kubernetes: Why a Dedicated Guardrail Microservice Matters When you expose an LLM‑powered API to the world, every request is a potential compliance risk. A single malformed prompt can surface PII, trigger a policy violation, or even cause a brand‑damaging output. In my experience, the first version of such a system is a set of ad‑hoc filters sprinkled across controllers. Under load, those filters become latency bottlenecks, policy updates race, and audit trails vanish. The root cause is a missing architectural layer that treats guardrails as a first‑class microservice that can scale horizontally, be updated live, and be observed independently. Guardrail Layer Requirements We need a guardrail layer that: Validates every request before it hits the LLM engine. Can be updated without redeploying the entire API surface. Provides per‑tenant isolation and versioning. Logs every decision for compliance and red‑team analysis. Runs at the same scale as the LLM inference service. When This Fails in Production Policy updates are applied via a shared ConfigMap and the pods do not reload, so new rules are never enforced. The guardrail service is single‑instance; a spike in requests triggers a queue that exceeds the LLM engine’s rate limit, causing a cascading failure. Audit logs are written to local disk; a pod crash loses events. Latency spikes because each request performs a synchronous Redis lookup for every policy. Common Mistakes Engineers Make Embedding guardrail logic inside the API controller rather than a dedicated middleware. Using in‑memory policy caches without a TTL, leading to stale rules. Ignoring the fact that
AI 资讯
ASP.NET Core Output Caching: How to Make Web APIs Faster in .NET
ASP.NET Core Output Caching: How to Make Web APIs Faster in .NET When an API receives the same request repeatedly, performing the same database query and rebuilding the same response every time can waste valuable resources. For example, imagine this endpoint: GET /api/products If thousands of users request the same product catalog, your application might repeatedly: HTTP Request ↓ Controller ↓ Database Query ↓ Business Logic ↓ JSON Response For data that doesn't change frequently, this can create unnecessary database load. ASP.NET Core provides Output Caching to help solve this problem. Instead of executing the complete request pipeline every time, the application can temporarily store the generated response and reuse it for subsequent requests. In this tutorial, we'll look at how Output Caching works, how to configure it, how to invalidate cached responses, and when you should avoid using it. What Is Output Caching? Output caching stores the generated response from an endpoint. For example: First request ↓ GET /api/products ↓ Execute controller ↓ Query database ↓ Generate response ↓ Store response in cache Later: Second request ↓ GET /api/products ↓ Cached response ↓ Return immediately The database doesn't need to be queried again while the cached response is valid. Output Caching vs Response Caching These two concepts are often confused. Response Caching Response caching mainly relies on HTTP caching semantics and headers. Output Caching Output caching is controlled by ASP.NET Core and allows your application to decide which responses should be cached and for how long. Output caching provides more control over server-side response caching. 1. Add Output Caching Start by registering the output-cache services. var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddOutputCache(); var app = builder.Build(); app.UseOutputCache(); app.MapControllers(); app.Run(); The important pieces are: AddOutputCache() ↓ Configure cac
AI 资讯
MFA Enabled Is Not MFA Verified
A two-factor flag in the user store looks like a reassuring authorization check. It tells us the account has a second factor configured. For a sensitive operation, however, that is only half the question. The other half is about the session in front of us: did this cookie actually complete a second-factor challenge? Those facts can change independently. Treating them as interchangeable can silently promote an old password-only session after the account enables MFA. Two questions that look like one Account capability answers questions such as: Is a factor enrolled now? Could the account complete an MFA challenge? Has that capability since been disabled? Session assurance answers different questions: Which authentication steps produced this session? Did the framework issue this cookie after an MFA challenge? Is the evidence trusted, or merely a user-supplied claim? An enrolled account can still have a password-only session. A previously verified session can also outlive a later change to the account’s factor state. One signal cannot safely stand in for both. The transition that exposes the gap Snapshot tests often miss this because the final state looks correct. The account has MFA enabled, the user is authenticated, and a policy succeeds. Now test the transition instead: Sign in with a password and receive a normal application cookie. Enable MFA for the account without replacing that cookie. Use the original cookie against a sensitive operation. If authorization checks only the current enrolment flag, step three may succeed. Nothing about the original authentication ceremony changed, but the session has effectively been upgraded by a later database write. That is the important boundary: changing account capability must not rewrite the history of an already-issued session. Use two independent signals A generalized policy can be expressed like this: if (! session . IsAuthenticated || ! session . HasTrustedMfaEvidence ) return Deny ; if (! await accountStore . IsMfaStil
AI 资讯
600 Filters and a 414: The New QUERY Method in .NET 10
A product search, a filter list that kept growing, and a status code I hadn't seen in years. Filters went in the query string, the way they always do. That held up fine until someone saved a "filter set" with a few hundred SKUs in it and the endpoint started answering with 414. I rebuilt a small version of it to find the exact wall. Same search, filters as repeated ?sku= values, count going up in steps of a hundred: 1) GET with filters in the URL 100 filters | request line 1534 bytes | 200 OK 200 filters | request line 3034 bytes | 200 OK 300 filters | request line 4534 bytes | 200 OK 400 filters | request line 6034 bytes | 200 OK 500 filters | request line 7534 bytes | 200 OK 600 filters | request line 9034 bytes | 414 RequestUriTooLong Kestrel's default max request line is 8 KB, and the request line is the method plus the URL plus the HTTP version. Somewhere between 500 and 600 filters, my URL stopped being a URL. Every fix I knew was a compromise. A body on GET is undefined by spec and some proxies quietly drop it. POST works, but POST announces "this might change something", so caches skip it, gateways won't auto-retry it, and anyone reading your API docs has to guess whether POST /search is actually a search. Cramming the filters into a header is the kind of idea that sounds clever for about a day. The method that was missing RFC 10008 defines QUERY , and it's exactly the thing that spot in the matrix was waiting for. The body carries the query. The method is safe and idempotent, so it can be retried after a dropped connection without anyone panicking. Responses are cacheable, and the spec is explicit that the cache key has to be built from "the request content and related metadata". There's also a nice touch on the response side: Content-Location can point at a URL where those exact results can be fetched with a plain GET. The one-line version I keep giving people: it's a GET with a body, and that's the entire point. Wiring it up in ASP.NET Core 10 .NET 10 shi
AI 资讯
Kiro as AI Partner for MS SQL Server Optimization on .NET Core: Yang Biasa Berhari-hari, Sekarang Hitungan Jam
Dulu, nyari query yang bikin database spike itu bisa makan berhari-hari. Yang nyari capek, yang nge-fix juga capek. Sekarang? Hitungan jam — dan bonusnya, sambil belajar hal baru juga. Ceritanya begini. Kalau kamu pernah kerja di aplikasi yang pakai ORM (Object-Relational Mapping — semacam "penerjemah otomatis" antara code dan database), pasti familiar sama situasi ini: database tiba-tiba lambat, kamu dapet raw query yang jadi biang kerok, tapi di codebase kamu nulis pakai syntax ORM yang bentuknya beda jauh dari SQL mentah itu. Buat yang belum pernah deal sama ORM, bayangin gini: kamu nulis pesan dalam bahasa Indonesia, lalu ada "penerjemah otomatis" yang convert jadi bahasa Jepang sebelum dikirim ke penerima. Suatu hari ada masalah di pesan yang terkirim — tapi kamu cuma bisa lihat versi bahasa Jepang-nya. Nyari bagian mana dari tulisan Indonesia kamu yang bikin terjemahan-nya bermasalah? Itu effort-nya yang bikin pengen balik tidur aja. Sekarang dengan bantuan Kiro, cukup kasih raw query + akses ke codebase, dia otomatis nyari bagian mana di code yang nge-generate query bermasalah itu. Yang dulu butuh berhari-hari, sekarang bisa selesai dalam hitungan jam — dan itu baru tahap investigasi, belum termasuk fixing-nya. Ceritanya Kenapa Bisa Pakai Kiro Akhir-akhir ini lagi aktif pakai Kiro di tempat kerja. Awal tahun lalu kantor dapat credits melalui program Kiro for Startup , jadi ya sekalian dimaksimalkan. Selain buat debug dan explore query di MS SQL Server, kadang pakai Kiro juga buat analisa log AWS CloudWatch — sambil kasih context aplikasi yang running biar analisa-nya lebih akurat dan gak generic. Di tulisan kali ini, saya mau sharing gimana pakai Kiro sebagai partner beberapa minggu terakhir buat improve query performance di aplikasi .NET Core. Kenapa "partner"? Karena Kiro-nya gak boleh langsung akses ke database — jadi wajib melalui perantara saya. Kita discuss, kolaborasi, dan nge-solve bareng. Bukan AI yang dikasih tombol terus disuruh jalan sendiri. Wakt
AI 资讯
Blazor SSR Gets Client-Side Validation in .NET 11 Preview 5 — No More Round-Trips Just to Show a Red Border
Blazor SSR Gets Client-Side Validation in .NET 11 Preview 5 If you've built Blazor Server-Side Rendering (SSR) forms, you know the pain: a user fills out a form, hits submit, the form posts to the server, the server runs validation, and only then does the user see the "This field is required" message next to the empty email field. That round-trip latency adds up. It breaks the immediacy users expect from modern web apps. .NET 11 Preview 5 fixes this. Blazor SSR forms now get instant, in-browser validation feedback — no server required. The server renders your validation rules as metadata, and Blazor's JavaScript enforces them client-side. Same DataAnnotationsValidator component you already use. Zero code changes needed. Let's break down how it works. Before .NET 11: The SSR Validation Gap In .NET 8 and 9, Blazor SSR rendered HTML on the server and sent it down. Validation only ran server-side — on form submission. If a field was invalid, the whole form posted to the server, came back with validation messages, and re-rendered. Interactive Blazor modes (Server, WebAssembly, Auto) had instant client-side validation because an active SignalR circuit or WASM runtime ran the validation logic locally. But SSR mode — the simplest, most performant option — was left out. The result? Developers who chose SSR Blazor for its simplicity had to choose between: Accepting the laggy validation UX Adding a second JavaScript validation library (and maintaining two validation rulesets) Re-architecting to use an interactive render mode None of these are great options. What Changed in .NET 11 Preview 5 The .NET team shipped two PRs ( #66441 and #66420 ) that bring unobtrusive client-side validation to Blazor SSR forms. The key insight: The .NET model stays the single source of truth. On form render, the server serializes your DataAnnotations validation rules into HTML metadata attributes. Blazor's JavaScript reads those attributes and applies them client-side — the same approach ASP.NET M
AI 资讯
F# vs C# 3 — Conclusions
What can I say. Anyone claiming that F# is good mostly for finance and data processing and C# for everything else, has probably never written a single line of practical F# code. In previous two parts of the article, I tried to demonstrate that with F# you can achieve the same goals as with C#, but with less verbose, repetitive, structural code. How it started. At some point, developers realized that global state with unrestricted data access causes many side effects, producing insecure, error-prone, and hard-to-maintain code as software grows larger. That is when the idea emerged to bring data and the code operating on it together into a single unit, restricting direct access to the unit’s internal state and making software more secure and predictable. This is how data encapsulation was born. Alongside encapsulation, abstraction was introduced — the process of hiding how behavior works. Encapsulation ( hiding data ) and abstraction ( hiding behavior ) remain two foundational pillars of Object-Oriented Programming. And that is how OOP has worked ever since — developers bring data and behavior together ( classes ) and define abstractions for them ( interfaces ). For example, for C# developers — including myself — this has become a daily routine. And we rarely question it, because OOP languages like C# leave us little choice but to structure code this way. But if you ask yourself whether this repetitive routine is always necessary, the answer is — no. You don’t need OOP concepts to build stateless, streamlined request–response, data-processing pipelines, because in such systems there is no long-lived state to hide and protect. You have a request, and almost immediately you have a response. After that, everything is gone. That is what I tried to demonstrate in the first two parts of this article by applying FP concepts. And even if you have a classical desktop application, you don’t always need to approach it in an OOP way. Functional programming handles side effects no