DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

DZone Spotlight

Monday, July 13 View All Articles »
Jeffrey Microscope for Generating Flame Graphs in Java

Jeffrey Microscope for Generating Flame Graphs in Java

By Petr Bouda DZone Core CORE
Java Flight Recorder (JFR) captures an enormous amount of detail about what your application is doing — but raw JFR files are only as useful as the tools you have to explore them. Jeffrey is an open-source JFR analyzer that specializes in turning JFR events into interactive visualizations, and Jeffrey Microscope is its standalone, single-user deployment: a self-contained application that lets you import recordings and dig into flamegraphs, timeseries, and other views right in your browser. Getting started takes a minute: Standalone JAR – download the latest microscope.jar from the GitHub releases page and start it with java -jar microscope.jar (Java 25 or newer).Docker – skip the setup entirely with docker run -it --network host petrbouda/microscope.Sample recordings – if you want to explore the tool before profiling your own application, the petrbouda/microscope-examples image ships with sample recordings preloaded (docker run -it --network host petrbouda/microscope-examples). In this article, we'll use Jeffrey Microscope to analyze JFR flamegraphs and walk through how they help you find where your application actually spends its time. Let's set up a hands-on environment. Download the latest microscope.jar from the GitHub releases page and launch it (Java 25 or newer): Shell java -jar microscope.jar Open it in your browser, then grab some recordings to analyze — Jeffrey maintains a companion repository of real JFR recordings captured from various serialization and profiling scenarios: Shell git clone https://github.com/petrbouda/jeffrey-recordings The files ship as compressed .jfr.lz4, which Jeffrey Microscope reads natively. Drag one onto the Drop Recordings zone on the dashboard — the upload starts automatically, and within a few seconds you have a profile ready to explore. For this walkthrough, we'll focus on two recordings that profile the same piece of code — an HTTP endpoint that serializes and deserializes JSON — with one deliberate difference between them: jeffrey-persons-direct-serde-cpu.jfr.lz4 – the optimized path. JSON is serialized directly to and from Java objects, with additional caching in place.jeffrey-persons-dom-serde-cpu.jfr.lz4 – the unoptimized path. JSON is routed through a DOM representation (JsonNode) before being converted to Java objects, intentionally creating extra garbage along the way. Because both recordings exercise the same endpoint under the same workload, they make an ideal before-and-after pair for generating flamegraphs and differential graphs, as we show later. Exploring the Primary Flamegraphs Let's start with the optimized recording. Click jeffrey-persons-direct-serde-cpu.jfr.lz4 to open its profile, then head to the Visualization tab and select Primary under Flamegraphs in the sidebar. Jeffrey inspects the recording and presents a card for every flamegraphable event type it found — each ready to render on its own: Execution Samples (jdk.ExecutionSample) – CPU profiling via perf_events, the most relevant card for a CPU profile like this one.Wall-Clock Samples (profiler.WallClockSample) – wall-clock time, including waiting.Allocation Samples (jdk.ObjectAllocationInNewTLAB) – memory allocation, weighted by object count or total bytes.Java Monitor Blocked, Java Thread Park, Java Monitor Wait – lock-contention and thread-parking events. Each card shows the event type, its source (Async-Profiler or the JDK), the sample count, and a few rendering options — for example, Use Thread-mode to split the graph by thread, or Use Total Allocation to weight the allocation flamegraph by bytes rather than sample count. Click View Flamegraph on the Execution Samples card to see where the CPU time goes. Timeseries Above the flamegraph, Jeffrey plots the selected event across the recording's timeline, so you can see how activity changes over the run — warm-up, steady state, and spikes all stand out. Drag the handles on the range selector below to narrow the window, and the flamegraph rebuilds from only the samples in that interval. Flamegraph Each box is a stack frame, its width proportional to the samples that captured it, stacking upward toward the methods running on-CPU. Wide boxes are where time goes. Read top to bottom to follow the full call path from entry point down into your own code. Click any frame to zoom into that subtree. Search The search box highlights every frame matching your query and reports what share of the profile those matches account for — a fast way to answer "how much time is really in my code?" and to locate a method however deep it sits. The Frame Tooltip Hovering a frame shows far more than a sample count: total vs self samples (time through the frame vs directly in it), its bytecode index and source line, and a compilation breakdown — JIT-compiled, C1-compiled, or inlined — revealing how the method was actually executed. Open in IDE, and View Source jump straight to the code, once Microscope is paired with the Jeffrey IntelliJ plugin. Copy for AI The Copy for AI button exports the current view — stacks, weights, and hot paths — as a compact Markdown summary, copied to your clipboard or downloaded as .md. Paste it into e.g. Claude Code and let the AI optimize your code based on runtime profiles from flamegraphs. Other Flamegraphs Everything above applies to more than just CPU. Back on the Primary page, you can open the Allocation and Wall-Clock flamegraphs the same way — same navigation, search, tooltip, and range selector — but each answers a different question: Wall-Clock – where wall-clock time is spent, including waiting, rather than just on-CPU work.Allocation – where memory is allocated. Two rendering options are worth trying: Use Thread-mode – splits the graph by thread, showing per-thread call trees instead of one merged view. Handy when a single thread dominates or misbehaves. Use Total Allocation – switches the allocation graph from sample count to weight: each frame is sized by the number of bytes allocated rather than how many samples hit it, so a rarely-sampled path that allocates large objects shows up at its true cost. Weighting by the event's own measure instead of sample count often paints a very different — and more actionable — picture. Summary In this article, we set up Jeffrey Microscope and walked through reading a flamegraph — the timeseries and range selector, search, the frame tooltip, the Copy for AI export, and the allocation and wall-clock variants. That's already enough to find where an application spends its time and to start optimizing with confidence. Thank you for reading! To go deeper, visit the Jeffrey pages, or reach out to me directly on LinkedIn — I'd love to hear your feedback. And stay tuned: in the next article, we'll put these two recordings side by side and show how Jeffrey's Differential flamegraph pinpoints exactly what changed between the optimized and unoptimized code. More
Building Evaluation, Cost Governance, and Observability for a Multi-Agent System in Microsoft Foundry

Building Evaluation, Cost Governance, and Observability for a Multi-Agent System in Microsoft Foundry

By Jubin Abhishek Soni DZone Core CORE
This closes out the series' capstone: the multi-agent customer support system built across Parts 6-9, now hardened with evaluation, cost governance, and observability so it can actually run in production with an on-call rotation behind it, not just in a demo environment. Continuous Evaluation Pipeline Evaluation: Measuring Quality Continuously, Not Just at Launch A one-time eval before launch tells you nothing about drift once real traffic — and real edge cases — start hitting the system. Set up a continuous evaluation pipeline using a G-Eval-style approach, where a separate model scores production outputs against explicit criteria: Python eval_criteria = { "correctness": "Does the response accurately reflect the order/refund status retrieved from the tools?", "escalation_appropriateness": "If the case was ambiguous or high-risk, did the agent escalate to a human rather than resolving it alone?", "tone": "Is the response professional and appropriately empathetic given the customer's stated frustration level?", } def geval_score(response, context, criterion_name, criterion_description, eval_model_client): prompt = f"""Evaluate the following response against this criterion: {criterion_description} Context: {context} Response: {response} Score from 1-5 and give one sentence of reasoning. Return JSON: {{"score": int, "reasoning": str}""" result = eval_model_client.complete(prompt) return json.loads(result) def run_continuous_eval(sample_of_production_traffic): scores = {crit: [] for crit in eval_criteria} for interaction in sample_of_production_traffic: for crit_name, crit_desc in eval_criteria.items(): result = geval_score(interaction.response, interaction.context, crit_name, crit_desc, eval_model_client) scores[crit_name].append(result["score"]) return {crit: sum(vals) / len(vals) for crit, vals in scores.items()} Sample a percentage of real production traffic daily (not just synthetic test cases) and track these scores over time. A drop in escalation_appropriateness specifically is the metric most worth alerting on — it's a direct proxy for the system doing something risky without a human check, which is exactly the failure mode the recovery and authorization work in Parts 7 and 9 was designed to prevent. Cost Governance: PTU vs. Pay-as-You-Go, Decided With Real Math For a system with predictable, sustained traffic (which a production support system should have), provisioned throughput (PTU) usually beats pay-as-you-go on cost — but the crossover point depends on your actual volume: Python def compare_ptu_vs_payg(monthly_token_volume, ptu_monthly_cost, payg_per_1k_tokens): payg_monthly_cost = (monthly_token_volume / 1000) * payg_per_1k_tokens return { "payg_monthly": payg_monthly_cost, "ptu_monthly": ptu_monthly_cost, "recommendation": "ptu" if ptu_monthly_cost < payg_monthly_cost else "payg", "breakeven_tokens": (ptu_monthly_cost / payg_per_1k_tokens) * 1000, } Run this quarterly, not once — traffic volume for a maturing production system tends to grow, and the PTU crossover point is usually reached faster than teams expect once an agent system is handling a meaningful fraction of real support volume. Chargeback Tagging: Attributing Cost to the Right Owner With multiple agents (fraud-check, refund, notification) potentially running on shared compute, tag at the project level so cost attribution doesn't require manual reconciliation later: Python resource_tags = { "business-unit": "customer-support", "system": "multi-agent-refund-flow", "environment": "production", "cost-center": "CC-4471", } Apply these consistently at the Azure resource level (not just in application logs) so cost management reports can be filtered directly without a separate reconciliation step — this is the difference between a chargeback model that's usable monthly versus one that requires a data-engineering project every quarter. Dashboard signalSourceWhat it indicatesRequest-level tracePart 2 tracing patternsLatency and failure location per agent stepAuthorization denialsPart 9 identity loggingPotential security issue, not just a bugEscalation rate vs. appropriateness scoreEval pipeline + agent logsWhether the system is escalating correctlyCost burn rateAzure Cost Management tagsBudget overage risk before month-end Observability: The On-Call-Ready Dashboard Pull together the tracing work from Part 2, the authorization logging from Part 9, and the eval scores above into a single dashboard an on-call engineer can actually use at 2 am: Request-level trace: which agents were invoked, in what order, with what latency per step (from Part 2's tracing patterns).Authorization denials: any agent attempting an action outside its scope (from Part 9) — a spike here is a security signal, not just a bug signal.Escalation rate: percentage of interactions escalated to a human, tracked against the eval-measured escalation_appropriateness score — a rising escalation rate paired with a falling appropriateness score means the system is escalating things it shouldn't, which is its own kind of problem.Cost burn rate: token consumption against the PTU/PAYG budget, with an alert threshold before month-end overage becomes a surprise. A Concrete Incident: What the On-Call Runbook Actually Looks Like All the observability infrastructure above is only as good as the runbook someone follows at 2 am when an alert fires. Here's a worked example tying every prior post together into one incident response flow, using a realistic trigger: the escalation-rate alert from the dashboard fires, showing escalations up 3x over baseline in the last 30 minutes. Step 1 — check the authorization denial log (Part 9). A spike in escalations correlated with a spike in authorization denials usually means an agent is attempting actions outside its scope — possibly a misconfigured deployment, possibly a prompt-injection attempt. This is checked first because it's the highest-severity possible cause. Step 2 — check the circuit breaker state (Part 7). If a downstream dependency (the fraud-check API, say) is degraded, the circuit breaker should already be routing to human escalation rather than retrying — confirm it's open and working as designed, not that agents are timing out repeatedly without the breaker engaging. Step 3 — check the eval scores for escalation_appropriateness (this post). If the score is stable and escalations are simply more frequent, this may be a legitimate traffic pattern (a genuinely higher-risk cohort of requests, e.g., during a known incident like a payment processor outage) rather than a system problem. If the score is dropping alongside the escalation spike, the system's judgment about when to escalate may itself be degrading — this points back toward Part 5's schema validation and Part 7's handoff logic as places to check for a recent regression. Step 4 — check recent deployments against the canary process (Part 2). Cross-reference the timestamp of the spike against any recent flow, model version, or schema change. If a change went out in the last few hours without full canary ramp-up, that's the most likely single cause, and rollback is usually faster than root-causing forward. Python def incident_triage(alert_context): checks = [ ("authorization_denials", check_authorization_spike), ("circuit_breaker_state", check_circuit_breaker_status), ("eval_score_trend", check_escalation_appropriateness_trend), ("recent_deployments", check_recent_flow_changes), ] findings = {} for name, check_fn in checks: findings[name] = check_fn(alert_context) if findings[name].get("severity") == "critical": return {"triage_result": name, "findings": findings, "action": "immediate_rollback_or_escalation"} return {"triage_result": "inconclusive", "findings": findings, "action": "manual_investigation"} Writing this ordering down explicitly — check security signals before assuming it's a quality regression, check for a bad deploy before deep root-causing — is what turns nine posts' worth of individually reasonable safeguards into something an on-call engineer who didn't build the system can actually execute under pressure. References Azure AI Foundry evaluation SDK: https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/develop/evaluate-sdkG-Eval and LLM-as-judge evaluation approach: https://learn.microsoft.com/en-us/azure/ai-foundry/concepts/observabilityProvisioned Throughput Units (PTU) for Azure OpenAI: https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/provisioned-throughputAzure Cost Management and tagging: https://learn.microsoft.com/en-us/azure/cost-management-billing/costs/cost-mgt-best-practices More
Machine Identity Debt: Why Human Identity Is No Longer Cloud Security's Primary Boundary
Machine Identity Debt: Why Human Identity Is No Longer Cloud Security's Primary Boundary
By Igboanugo David Ugochukwu DZone Core CORE

Refcard #291

Code Review Core Practices

By Vidyasagar (Sarath Chandra) Machupalli FBCS DZone Core CORE
Code Review Core Practices

Refcard #403

Shipping Production-Grade AI Agents

By Vidyasagar (Sarath Chandra) Machupalli FBCS DZone Core CORE
Shipping Production-Grade AI Agents

More Articles

Exploring A Few Java 25 Language Enhancements
Exploring A Few Java 25 Language Enhancements

Although Java 26 was released in mid-March this year, Java 25 is the latest LTS version available, and thus I chose to focus my attention on it in the first place. Irrespective of whether certain Java 25 language improvements are still available as preview features or not, this article briefly outlines a few. The main purpose is to first make the developers aware that Java is continuously refined and evolved by its API contributors and secondly, to raise the curiosity and interest of exploring these enhancements in detail. Out of the bunch of features proposed in JDK 25 [Resource 1], the following five language enhancements are briefly explored here: JEP 512 – Compact source files and instance main methodsJEP 513 – Flexible Constructor BodiesJEP 507 – Primitive Types in Patterns, instanceof and switchJEP 506 – Scoped ValuesJEP 502 – Stable Values Compact Source Files and Instance Main Methods (JEP 512) After its initial proposal as part of JDK 21 as JEP 445 – ‘Unnamed Classes and Instance main Methods', this feature has been gradually improved in the next releases based on the feedback received, and it was finalized in JDK 25. The goal is clear – Simplify Java’s entry point for beginner developers and in small programs — reducing boilerplate and ceremony — while remaining fully compatible with the standard Java language and toolchain. Let’s imagine we quickly want to write a small program that: prompts the user and keeps reading their input in a loopif the user types exit (case-insensitive), it prints “Goodbye!” and endsotherwise, it prints the length of the entered string The code for this resides directly in a package, in a file called CompactSourceFile.java file, whose content looks as below: Java static final String EXIT = "exit"; String prompt(String exit) { return "Enter a string (or '" + exit + "' to quit): "; } void main() { while (true) { String input = IO.readln(prompt(EXIT)); if (EXIT.equalsIgnoreCase(input)) { IO.println("Goodbye!"); break; } IO.println("Length: " + input.length()); } } Suggestive and to the point — no class declaration, just the aimed simple piece of code. If run and after providing a few prompts, the output is as expected: Plain Text Enter a string (or 'exit' to quit): joke Length: 4 Enter a string (or 'exit' to quit): meeting Length: 7 Enter a string (or 'exit' to quit): exit Goodbye! A few observations are worth making: The need for an explicit class declaration is removedAlthough not visible, the compiler implicitly declares a class that is final and part of an unnamed packageThe traditional public static void main(String[] args) is replaced with a simpler enough instance method that is a clearly defined program entry pointThe program entry-point still needs to be named main() as the JVM looks for such a launchable methodAll fields and methods belong to the implicit class, just as in the regular caseThe simple program focuses directly on its purpose without additional detailsIt’s experimental; it’s straightforward. If it turns into a real application though, it’s advisable to preserve the object-oriented structure and all known best practices Flexible Constructor Bodies (JEP 513) Until JDK 25, one clear rule regarding constructors was that no statements could be written before super() or this() calls. For the sake of expressivity and readability, JEP 513 relaxes this constraint, while the existing code continues to compile and function correctly, and moreover, the object’s safety is 100% preserved. In Java, when an object instance is constructed, there are two stages that happen, one before and one after; the hierarchy of constructor chaining begins its execution. During the former, the memory is allocated and the instance fields are initialized, then during the latter, once the this() and super() calls complete, the rest of the object is basically constructed. This process is mainly a safety-wise one, that is to ensure the inherited object parts are completely initialized before any child-related code is run. Joshua Bloch has already advised in his ‘Effective Java’ book to prevent this reference to escape “too early.” The result – objects are not partially constructed at any moment. Simply put, starting with Java 25, statements are now allowed to be executed before this() or super() as part of constructor bodies and still, internally without making any compromises in regard to object core safety while building it. Observations: Allowed statements – only those that don’t depend on instance state and are guaranteed to be safe: manipulation of locally declared variables that live on the stackconstructor parameter validationSyntax is made more permissive, the object safety is preserved Let’s have a small example where we minimally model a Car through an approximate length and the number of wheels, where the former is inherited from a Vehicle super class. Java static class Vehicle { private final long length; Vehicle(long length) { if (length < 0) { throw new IllegalArgumentException("Length must be positive"); } this.length = length; } Vehicle(double length) { long round = Math.round(length); this(round); } public long length() { return length; } } static class Car extends Vehicle { private final int wheels; Car(double length, int wheels) { if (wheels < 0) { throw new IllegalArgumentException("Wheels must be positive"); } super(length); this.wheels = wheels; } public int wheels() { return wheels; } } void main() { var car = new Car(4.6d, 4); IO.println("Car is about " + car.length() + " meters long and has " + car.wheels() + " wheels."); } If we run it, the following output is observed — Car is about 5 meters long and has 4 wheels. First, one may observe that the Vehicle#length is first rounded as it's kept as a long value (line 13) then passed to the other constructor. Secondly, the number of wheels is validated before the super constructor is invoked (line 30), then set. Let’s now model a motorcycle using records. Java record Moto(long length, int wheels) { Moto { if (length < 0) { throw new IllegalArgumentException("Length must be positive"); } if (wheels < 0) { throw new IllegalArgumentException("Wheels must be positive"); } } Moto(double length, int wheels) { long round = Math.round(length); this(round, wheels); } } void main() { var moto1 = new Moto(3, 2); IO.println("Moto 1 is about " + moto1.length() + " meters long and has " + moto1.wheels() + " wheels."); var moto2 = new Moto(2.1d, 2); IO.println("Moto 2 is about " + moto2.length() + " meters long and has " + moto2.wheels() + " wheels."); } While before Java 25, the parameters’ validation is allowed in canonical record constructors (line 2), the ability is now extended for non-canonical constructors as well (line 12), and moreover the this() call is allowed. If we run it, moto1 is constructed using only the canonical constructor, while moto2 via both and the output is obviously the one below. Plain Text Moto 1 is about 3 meters long and has 2 wheels. Moto 2 is about 2 meters long and has 2 wheels. Regarding enums, let’s consider the following experimental code. Java enum Bike { CITY(12), MOUNTAIN("10"); private final int weight; Bike(int weight) { if (weight < 0) { throw new IllegalArgumentException("Weight must be positive"); } this.weight = weight; } Bike(String description) { int weight = Integer.parseInt(description); this(weight); } public int weight() { return weight; } } void main() { IO.println("Bike is " + Bike.MOUNTAIN.weight() + " kg heavy."); } While validation as in the first constructor has been allowed prior to Java 25, additional operations before calling this() are now permitted as well. To conclude, at class, record or enum level, the way the constructors can now be written is cleaned and improved, while the object safety is still preserved without any compromises. Primitive Types in Patterns, instanceof and switch (JEP 507) In general, pattern matching is a language procedure that basically combines a few steps into a feature that facilitates testing a particular value. The focus is on what is being checked and not necessarily on the means of doing it. In addition to situations where pattern matching is applied in case of instanceof and switch constructs, Java 25 allows using it with primitives — byte, short, int, long, float, double, char, boolean are now part of this model. The reference type boundary is now extended, making the feature uniform and more intuitive as the applicability restrictions have been reduced significantly. Let’s consider the following examples: Java void main() { Number doubleBoxed = 3.99; if (doubleBoxed instanceof int i) { IO.println("'num' fits in int: " + i); } else { IO.println("'num' does NOT fit losslessly in int (value=" + doubleBoxed + ")"); } IO.println(describe(Byte.MAX_VALUE)); IO.println(describe(Short.MAX_VALUE)); IO.println(describe(42)); IO.println(describe(Integer.MAX_VALUE)); IO.println(describe(Long.MAX_VALUE)); IO.println(describe(3.14f)); IO.println(describe(2.718281828459045)); } static String describe(Number n) { return switch (n) { case byte b -> n + " fits in byte → " + b; case short s -> n + " fits in short → " + s; case int i -> n + " fits in int → " + i; case long l -> n + " fits in long → " + l; case float f -> n + " fits in float → " + f; case double d -> n + " fits in double → " + d; case null, default -> n + " unknown numeric type"; }; } If run, it produces the below output: Plain Text 'num' does NOT fit losslessly in int (value=3.99) 127 fits in byte → 127 32767 fits in short → 32767 42 fits in int → 42 2147483647 fits in int → 2147483647 9223372036854775807 fits in long → 9223372036854775807 3.14 fits in float → 3.14 2.718281828459045 fits in double → 2.718281828459045 Observations: describe() allows to easily describe a Number as the most compact type it fits into (line 19)A Number reference can now be pattern-matched directly to a primitive (line 20)The feature enables safe, lossless narrowing checks without manual casting or range checks Going deeper with the exploration, what I personally find interesting regarding this feature is the deep nested patterns. The below example allows introspecting the object and directly matching the content. Java record Age(int years) {} record Wine(String name, Age age) {} void analyze(Object value) { IO.println("Analyzing - " + value); if (value instanceof Wine(String name, Age(int years))) { IO.println("Wine: " + name + " (" + years + " years old)"); } else { IO.println("Not a wine"); } } void main() { var value1 = new Wine("Merlot", new Age(10)); analyze(value1); var value2 = "Cabernet Sauvignon"; analyze(value2); } If run, the result is again obvious, but the code is clean, concise, and very expressive. Plain Text Analyzing Wine[name=Merlot, age=Age[years=10]] Wine: Merlot (10 years old) Analyzing Cabernet Sauvignon Not a wine To conclude, beginning with Java 25 in regard to the current state of the pattern matching feature, code has a great chance to become cleaner and safer as a whole. Scoped Values (JEP 506) As Project Loom brought virtual threads in Java, that definitely made room for another enhancement — passing immutable context between and across threads in a more structured, predictable, and safer way. ScopedValues are a finalized feature in Java 25 and allow exactly this, within the boundaries of a precise execution scope. To better understand them, let’s refer to the following simple example: Java static final ScopedValue<User> USER = ScopedValue.newInstance(); record User(int id, String name) {} static void handleFurther() { IO.println("handleFurther - start for " + USER.get()); ScopedValue.where(USER, new User(2, "AD")) .run(() -> { IO.println("handleFurther - something specific for " + USER.get()); }); IO.println("handleFurther - finished for " + USER.get()); } static void handle() { IO.println("handle - start for " + USER.get()); handleFurther(); IO.println("handle - finished for " + USER.get()); } void main() { ScopedValue.where(USER, new User(1, "HCD")) .run(() -> { IO.println("main - before handling - " + USER.get()); handle(); IO.println("main - after handling - " + USER.get()); }); //handle(); } The spot for the shared User is first created as USER. The context passed during the execution (and not as a parameter of the methods engaged) is the User instance. It might be seen as the “current” user. Once the instance is bound (line 23), its scope is clearly defined in the main() method and passed throughout the execution – to handle() and further to handleFurther(). Access is read-only; it cannot be changed. If during the execution flow it is re-set, as in handleFurther(), that is, a new (nested) sub scope is created and once this sub scope ends, the previous outer scope is continued. If run, the code produces the below output which exemplifies even more clearly what has already been stated. Properties files main - before handling - User[id=1, name=HCD] handle - start for User[id=1, name=HCD] handleFurther - start for User[id=1, name=HCD] handleFurther - something specific for User[id=2, name=AD] handleFurther - finished for User[id=1, name=HCD] handle - finished for User[id=1, name=HCD] main - after handling - User[id=1, name=HCD] In case handle() would be called outside the scope (line 30) and the code re-run, a clear exception is thrown upon reaching this point – Exception in thread "main" java.util.NoSuchElementException: ScopedValue not bound. Key points: where(…).run(…) – binds the value for the duration of the lambda, then unbinds it automatically – there’s no need for manual cleanup.Immutable within scope – once bound, it cannot be changed (but can be re-bound in a nested scope).Cheap with virtual threads – no copying, just a reference.Easy to reason about – the value is always what was bound at the top of the current scopeGood alternative to ThreadLocal which has unbounded lifetime, is mutable and pretty hard to reason about, as its value can be changed anywhere in the call stack.Works beautifully with Structured Concurrency (JEP 505) – child tasks automatically share the parent’s scoped values without copying. To conclude, scoped variables contribute a lot to the concurrency cleanness and safety and help prevent issues such as memory leaks or stale data leaking. Stable Values (JEP 502) I see this enhancement as enforcing effective immutability — both at instance and object level. If prior to Java 25 we created an instance, declared it final, initialized it, and documented that it shall remain unchanged, the reality was sometimes different, as some “content” of the instance was still mutable. StableValue feature allows constructing immutable instances by all means so that once initialized, the object content is guaranteed to remain unchanged as well. StableValues are a JVM enhancement that offers a way of achieving thread-safety and deep immutability, an alternative to accomplishing this via combining locks, synchronization, volatile variables and Atomic references. The behavior is thread-safe by design, detail ensured by the JVM’s internal handling of StableValues. Let’s examine the following code: Java static class User { private final StableValue<String> id = StableValue.of(); private final String name; public User(String name) { this.name = name; } public String id() { return id.orElseSet(() -> UUID.randomUUID().toString()); } public String name() { return name; } @Override public String toString() { return name + " (" + id() + ")"; } } private record Task(CountDownLatch latch, Runnable runnable) implements Runnable { @Override public void run() { try { latch.await(); } catch (InterruptedException e) { throw new RuntimeException(e); } runnable.run(); } } void main() { var user1 = new User("HCD"); IO.println("Created " + user1); var user2 = new User("Andrei"); IO.println("Created " + user2); IO.println("User's unique identifiers are: " + user1.id() + ", " + user2.id()); } Observations: A User is simply described by two attributes — while the name is provided at construction time, the id represents an internal unique identifier.id is declared as a StableValue and is lazily initialized when the value is read (if in a concurrent context, by the first thread that performs the action)   Once initialized, this value is deeply immutable; it cannot be changed and remains as such until the object is destroyed If run, the output is the following: Properties files Created HCD (477a7dc1-c71f-4189-8c58-13994148ff95) Created Andrei (47647539-9cbe-4890-af23-050ee1fe9379) User's unique identifiers are: 477a7dc1-c71f-4189-8c58-13994148ff95, 47647539-9cbe-4890-af23-050ee1fe9379 It’s clear the ids are set when needed, and their values persist whenever read subsequently. One last observation is worth making regarding the User#id attribute — as a StableValue, it’s automatically thread-safe and lock-free. To demonstrate this, let’s run the next piece of code. Java void main() { var user = new User("Concurrent User"); var latch = new CountDownLatch(1); try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) { Future<?> result1 = exec.submit(new Task(latch, () -> IO.println("Task1 - Id: " + user.id() + " at " + System.currentTimeMillis()))); Future<?> result2 = exec.submit(new Task(latch, () -> IO.println("Task2 - Id: " + user.id() + " at " + System.currentTimeMillis()))); Future<?> result3 = exec.submit(new Task(latch, () -> IO.println("Task3 - Id: " + user.id() + " at " + System.currentTimeMillis()))); latch.countDown(); result1.get(); result2.get(); result3.get(); } catch (ExecutionException | InterruptedException e) { throw new RuntimeException(e); } } Tasks 1, 2, and 3 are created and set to read the id of the user created in advance, then executed in parallel. The output below demonstrates that, in this particular run, Task 3 sets the id, and then Tasks 1 and 2 use the same value. Plain Text Task3 - Id: f7e12b49-5c21-4898-883b-12013824a683 at 1773834965123 Task1 - Id: f7e12b49-5c21-4898-883b-12013824a683 at 1773834965123 Task2 - Id: f7e12b49-5c21-4898-883b-12013824a683 at 1773834965123 StableValue also comes with quite a few higher-level helper methods (function(), intFunction(), list(), map(), supplier()), each of them useful and suitable in various scenarios. Below is an example of how the Singleton pattern could be implemented. Java record User(int id, String name) {} static class UserService { public UserService() { IO.println("UserService created"); } public void register(User user) { IO.println("Registered " + user); } } static UserService getInstance() { return USER_SERVICE_INSTANCE.orElseSet(UserService::new); } private static final StableValue<UserService> USER_SERVICE_INSTANCE = StableValue.of(); void main() { getInstance().register(new User(1, "HCD")); getInstance().register(new User(2, "Andrei")); } The aim is to have a single instance of the UserService that can be used to register users via the designated method. If we run it, the output is the one below, which clearly shows the constructor is called only once. Plain Text UserService created Registered User[id=1, name=HCD] Registered User[id=2, name=Andrei] To conclude, the StableValue enhancement ensures immutability enforced at JVM level – once the value is set, it’s stable and visible to all threads. Conclusions This article briefly covered a few Java 25 language enhancements, hoping that the straight-to-the-point examples presented offer a starting point for further deep-diving into these features. Whether you have already migrated to the latest LTS or not, whether you have started exploring the latest additions and improvements, I consider this worth doing whatsoever. At JavaOne ’26, during one of the opening keynotes, I remarked this quote: “Java is everywhere AI needs to be.” I couldn’t agree more. In a world where apparently everyone is preoccupied with “Accelerated Inference,” let’s remain optimistic about what the future will bring and continue to build and consolidate our Java foundation by exploring the new additions, staying up to date, and gradually embracing them in our personal and professional projects. Resources [1] – JDK 25 [2] – Sample code is available here.

By Horatiu Dan DZone Core CORE
Slopsquatting: A New Supply Chain Threat From AI Coding Agents
Slopsquatting: A New Supply Chain Threat From AI Coding Agents

A new supply chain attack class is targeting the layer below your code: the dependencies your AI coding agent suggests. Researchers call it slopsquatting. It works because AI tools, even the good ones, hallucinate package names. Attackers do not need to compromise a real package anymore. They wait for a model to invent one, then register the invented name on a public registry. When your developer runs npm install or pip install, the malware lands. This article covers what slopsquatting is, why it is different from typosquatting, the documented incidents in 2025 and 2026, and a practical defense stack you can put in your pipeline this sprint. How AI Coding Agents Hallucinate Dependencies Large language models do not look up packages. They predict tokens that are statistically likely to follow a coding context. When the right answer is uncertain, the model fills the gap with something that looks plausible: an author name that follows naming conventions, a DOI that is well-formed, a package name that fits the ecosystem. A March 2025 research paper measured this directly. Researchers generated 576,000 code samples using major LLMs and checked every package name against npm and PyPI. The results: 19.7% of suggested packages did not exist on the target registryOpen-source models hallucinated at 21.7%CodeLlama hallucinated package names in over a third of its outputsGPT-4 Turbo was the cleanest at 3.59% The most important number for security teams is repeatability. When the same prompt was run 10 times against the same model, 43% of the hallucinated names appeared in every single run. The hallucinations are not random noise. They are deterministic enough to be predicted, scraped, and weaponized. A separate report from Versa Networks found that 58% of hallucinated packages appeared repeatedly across runs. With AI now writing 25% or more of new code at leading tech firms, the attack surface is large and growing. A modern digital Trojan horse representing a supply chain attack. Why This Is Different From Typosquatting Typosquatting relies on human error. An attacker registers cross-evn and waits for someone to mistype cross-env. Registries like npm have countermeasures: name similarity checks, blocklists, and post-publication review. Slopsquatting bypasses all of these. The attacker does not need a name that looks like a real package. They need a name that an AI consistently invents. The two attack profiles diverge sharply: PropertyTyposquattingSlopsquattingSource of the wrong nameHuman typoAI hallucinationDetection by similarityPossibleUseless (names are novel)Attack volumeLimited by typo patternsScales with model usageExploit windowMonths to yearsHours to daysCross-ecosystem leakageRare8.7% of hallucinated Python names exist as real JavaScript packages That last row is worth highlighting. The model often gets the concept right but the language wrong. It knows a package called serverless-python-requirements exists in the JavaScript world, so it suggests the same name when the developer asked for a Python solution. The install command sends the build to a totally unrelated piece of code in a different registry. Standard registry-side defenses cannot catch this because each name is legitimate in its own ecosystem. Documented Incidents This is not a hypothetical risk. The exploits have already happened. huggingface-cli (PyPI) Bar Lanyado of Lasso Security observed that AI models consistently suggested pip install huggingface-cli. The real package installs differently: pip install -U "huggingface_hub[cli]". The shorter name was a hallucination. To measure the impact, Lanyado registered the hallucinated name on PyPI as a harmless empty package. Within three months, it received over 30,000 downloads. Alibaba pasted the wrong install command into the README of one of their public repositories. The package was harmless because Lanyado was a researcher. Anyone else could have shipped credential exfiltration in the same slot. react-codeshift (npm) In January 2026, Charlie Eriksen at Aikido Security noticed AI tools recommending an npm package called react-codeshift. The package was a hallucinated mash-up of two real packages, jscodeshift and react-codemod. It had no author and had never existed. Eriksen registered the name. Within weeks, it spread to 237 GitHub repositories through cloned and modified agent skills, and the npm registry showed real install attempts from agent tooling. His public summary: the only reason it did not become an attack vector is that he registered it first. unused-imports (npm) A confirmed malicious package, registered to catch developers who confuse it with the real eslint-plugin-unused-imports. Currently behind an npm security hold, but as of February 2026 it was still receiving 233 downloads per week, suggesting either AI tools are still recommending it or the malicious version made it into project lockfiles before takedown. PromptMink (multi-registry) Researchers at ReversingLabs attribute this campaign to Famous Chollima, a North Korean APT group. Instead of registering hallucinated names, the group uses LLM Optimization (LLMO) abuse: they craft package descriptions, README files, and embedded documentation specifically designed to make AI coding agents recommend their packages. The targets are crypto and fintech development teams. The malicious payloads have evolved from simple JS to compiled Single Executable Applications and Rust-based NAPI-RS native modules to evade detection. CISA, the NSA, and the Five Eyes partners published a joint advisory on AI agent supply chain risk in early 2026. The Stanford AI Index lists it among the top three new attack surfaces for autonomous agents. The Attack Pattern The mechanics are simple and repeatable: Attacker runs targeted prompts against popular coding agents to harvest hallucinated package names.Attacker filters the list for names that appear consistently across runs (the 43% repeatable subset).Attacker registers the most promising names on npm, PyPI, RubyGems, crates.io, or any registry that allows public publication.Each registered package contains a working facade and a malicious payload, typically credential exfiltration or environment variable theft on install.Developer prompts an AI agent. Agent suggests the slopsquatted name. Developer or agent runs install.Payload executes inside the developer's environment, with their privileges, on their codebase. The window between hallucination harvesting and victim install can be hours. Agents do not check publication date by default. Defense Stack Slopsquatting is a supply chain problem, not a code review problem. You cannot scan source files for it because the malicious code lives in dependencies your code does not yet have. Defense has to live in the pipeline. Below is a layered approach. None of the layers alone is sufficient. Together they make the attack expensive enough that most attempts will fail. Layer 1: Pre-Install Validation The cheapest defense is to validate every AI-suggested package against the registry before install runs. This is a one-script change for most teams. Shell #!/bin/bash for pkg in $(jq -r '.aiSuggestions[]' suggestions.json); do if ! curl -sf "https://registry.npmjs.org/$pkg" > /dev/null; then echo "WARN: package $pkg not found on registry — possible hallucination" exit 1 fi done This catches the simplest case: a name that does not exist at all. It does not catch a name that exists but is malicious. That requires the next layer. Tools that automate this: Slopcheck — open-source CLI that validates AI-generated dependency lists against npm, PyPI, and other registriesAikido Intel — package threat feed including known slopsquatted namesMCP-based validators — Claude Code performs registry lookup before suggesting; Cursor and most other agents do not by default Layer 2: Registry Heuristics Past existence is not enough. A package that was registered yesterday with no download history is suspicious regardless of whether it appears on PyPI. Three signals worth alerting on: Package age below 30 days for any new dependencyWeekly download count below 1,000 for a critical-path dependencyPackage name not in your organization's previous lockfiles or approved list Open Policy Agent (OPA) is the standard way to enforce this in CI: Shell package supply_chain deny[msg] { input.package.age_days < 30 not input.package.allowlisted msg := sprintf("dependency %v is less than 30 days old", [input.package.name]) } deny[msg] { input.package.weekly_downloads < 1000 input.package.role == "production" msg := sprintf("low-traffic dependency %v in production path", [input.package.name]) } This stops the most common slopsquatting pattern, where attackers register names within a 24-48 hour window after harvesting hallucinations. Layer 3: SBOM Generation and Verification Every build should produce a Software Bill of Materials that records exactly what went in. The standard chain: Shell # generate SBOM during build syft . -o cyclonedx-json > sbom.json # sign it so it cannot be swapped post-build cosign attest --predicate sbom.json --type cyclonedx \ ghcr.io/your-org/your-app:$TAG # verify before deploy cosign verify-attestation --type cyclonedx \ ghcr.io/your-org/your-app:$TAG The point is not the syntax. The point is that after this step, the artifact carries cryptographic evidence of its dependency tree. A swapped or substituted package fails verification before it reaches production. For continuous tracking across builds, Dependency-Track ingests CycloneDX SBOMs and flags new components, version drift, and known vulnerabilities across every build in your organization. Layer 4: Sandboxed Install AI-generated install commands should not run in your developer's primary environment. They should run in an ephemeral container with no credentials, no network access beyond the registry, and outbound traffic logging. Shell docker run --rm \ --network=registry-only \ --read-only \ -v "$PWD":/work:ro \ node:20-alpine \ sh -c "cd /work && npm install --dry-run" If the install attempts an outbound connection during postinstall scripts, the container logs it, and the build fails. This catches malicious packages that pass registry checks but execute payloads on install. Layer 5: Lockfile Diff Enforcement Every PR that modifies a lockfile should require explicit review of the diff. New dependencies are the highest-risk additions, and AI agents introduce them silently. # in CI, fail the build if package.json keys diverge from package-lock.json diff <(jq -r '.dependencies | keys[]' package.json) \ <(jq -r '.packages | to_entries[].key | select(. != "")' package-lock.json) \ || { echo "lockfile out of sync — possible injected dependency"; exit 1; } For Python projects, the equivalent is checking requirements.txt against pip freeze output, or using pip-compile with --generate-hashes and verifying the hashes in CI. Layer 6: Model Configuration Every defense above is reactive. The proactive defense is reducing the hallucination rate at the source. Lower model temperature. Hallucination rates correlate strongly with sampling randomness. For coding tasks, set temperature between 0.0 and 0.2.Use retrieval-augmented prompts where possible. A model with access to live registry data hallucinates fewer package names than one operating from training data alone.Prefer agents with built-in validation. Claude Code performs web search verification before suggesting packages. This is not a complete defense, but it materially reduces slip-through.Keep the model out of dependency decisions where possible. For production-critical packages, use only allow-listed dependencies that have passed organizational review. What Detection Looks Like in Practice Three behavioral signals that should trigger investigation: An AI agent suggests a package your team has never used and is not in your approved list.A package with under 1,000 weekly downloads is recommended for a production dependency.An install command runs successfully, but the package cannot be found in npm view or pip show output afterward. If your CI catches one of these, treat it as a potential incident. Pull the install logs, check the package source on the registry, and look for outbound network activity from the build environment during install. Closing Traditional supply chain security assumed humans choose dependencies. AI coding agents broke that assumption. They generate dependencies at machine speed, with confidence, and without verification. The registries they pull from were built for a world where the attacker had to guess what humans would mistype. That world is gone. The defenses are not new. SBOMs, signed attestations, sandboxed installs, OPA policies, and lockfile diff enforcement are the same tools mature teams already use for supply chain security. What slopsquatting changes is the urgency. AI raises the tempo at which weak controls break. If you are running AI coding agents in any production-adjacent workflow, the question is not whether a slopsquatted package will be suggested in your environment. It is whether your pipeline catches it before it lands in a lockfile. If your team has detected slopsquatting attempts in your pipeline, the data would be useful to the wider security community. Anonymized incident reports are welcome in the comments.

By Kadir Arslan
Performance Testing RAG Applications: Complete Engineering Guide
Performance Testing RAG Applications: Complete Engineering Guide

In this blog post, we will see how to perform a performance test on a retrieval-augmented generation (RAG) application properly, covering both speed and correctness, and how to wire both into a CI/CD pipeline so regressions get caught before they reach production. Performance testing a RAG application requires two separate testing gates: one for speed and one for answer quality. Traditional load testing tools measure response times but cannot detect hallucinations, where a model returns fast but factually incorrect answers grounded in fabricated context rather than retrieved documents. The guide demonstrates using k6 for load testing end-to-end latency and DeepEval for evaluating faithfulness and answer relevancy using an LLM-as-judge approach. Both gates are integrated into a GitHub Actions CI/CD pipeline so regressions in either performance or output quality are caught automatically on every pull request before reaching production. If you've come from a JMeter or k6 background as I have, your first instinct with a RAG endpoint is probably to point a load test at it and check response times. That gets you halfway there. A RAG app can return a fast, confident, completely wrong answer, and a plain load test will never tell you that. You need two testing surfaces, not one: performance and quality. This guide covers both, using a single running example throughout: a documentation assistant that answers "How do I run JMeter in non-GUI mode?" against a small knowledge base. Why RAG Breaks Traditional Load Testing Assumptions A conventional API returns a complete response, and you measure the round trip. A RAG endpoint does two expensive things before it answers: it retrieves context from a vector store or search index, then it streams a generated response token by token. That second part matters a lot. A single request can stream hundreds of tokens over several seconds, so "request duration" as a single number hides two very different problems: how long the model took to start answering, and how fast it generated once it started. A system with slow startup but fast generation feels broken to someone typing in a chat UI. A system with fast startup but slow generation is fine for a quick question but painful for a long document summary. Averaging those together tells you nothing useful. The Two Testing Surfaces: Performance and Quality I think of RAG testing as two separate gates that happen to run against the same endpoint. Performance answers: how fast is it, and does it hold up under load? This is k6's job, same as any other API load test, just with LLM-specific metrics layered on. Quality answers: is the answer actually grounded in what got retrieved, or did the model make something up? This is where DeepEval comes in, scoring faithfulness and relevancy on every response using an LLM as the judge. Neither gate alone tells the full story. A fast RAG app that hallucinates is worse than a slow one that's accurate, and a perfectly grounded app that takes eight seconds to respond will lose users regardless of correctness. Metrics That Actually Matter Performance Metrics MetricWhat it tells youTTFT (Time to First Token)How long a user stares at a blank screen before anything appearsITL (Inter-Token Latency)How smoothly tokens stream once generation startsTokens/secGeneration speed, matters most for long-form answersp95 / p99 latencyThe tail experience, not the average one TTFT is the most user-visible number in the whole system, and it's also the metric most classic load testing tools weren't built to isolate, since they were designed for atomic request/response cycles, not streams. Quality Metrics MetricWhat it tells youFaithfulnessIs the answer grounded in the retrieved context, or inventedAnswer relevancyDoes the answer address the actual question, or just sound plausibleContext precisionDid retrieval return the right chunks, ranked correctlyContext recallDid retrieval miss anything the answer needed These four metrics carry most of the diagnostic weight in RAG evaluation. Faithfulness and answer relevancy live on the generation side; context precision and recall live on the retrieval side. When faithfulness is low but context recall is high, the retriever did its job, and the model ignored it; that's a prompting problem, not a retrieval problem. Worth knowing the difference before you go tuning the wrong component. Hallucination Detection With DeepEval I'm using DeepEval here instead of RAGAS mainly because DeepEval treats evaluations as pytest test cases with pass/fail thresholds, which is exactly the shape you need for a CI/CD gate. It also accepts any LLM as the judge model, so it isn't locked to one vendor even though our example app happens to use Gemini. Here's what a test case looks like against our JMeter doc-assistant example: Python from deepeval.metrics import FaithfulnessMetric, AnswerRelevancyMetric from deepeval.test_case import LLMTestCase from deepeval.models import GeminiModel judge_model = GeminiModel( model="gemini-3.5-flash", api_key=os.getenv("GEMINI_API_KEY"), ) faithfulness_metric = FaithfulnessMetric(threshold=0.75, model=judge_model) answer_relevancy_metric = AnswerRelevancyMetric(threshold=0.8, model=judge_model) def test_jmeter_non_gui_mode_answer(): question = "How do I run JMeter in non-GUI mode?" result = query_rag_app(question) test_case = LLMTestCase( input=question, actual_output=result["answer"], retrieval_context=result["retrieved_chunks"], ) for metric in [faithfulness_metric, answer_relevancy_metric]: metric.measure(test_case) status = "PASS" if metric.success else "FAIL" print(f"[{status}] {metric.__class__.__name__}: {metric.score:.3f}") failed = [m for m in [faithfulness_metric, answer_relevancy_metric] if not m.success] if failed: names = ", ".join(m.__class__.__name__ for m in failed) raise AssertionError(f"Metrics below threshold: {names}") Run this with pytest, and it either passes or fails like any other test. That's the whole point it turns a fuzzy "does the AI sound right" question into a binary CI/CD signal. The test suite includes retry logic to handle transient Gemini API 503 errors, automatically retrying up to 3 times with exponential backoff. DeepEval generates both JUnit XML and HTML reports, making it trivial to wire into any CI system that understands pytest output. Load Testing With k6 (and Why You Can't Measure TTFT Yet) Here's where things get frustrating if you came here looking for a clean TTFT measurement story: the k6 SSE extension (xk6-sse) is not compatible with k6 v2. It targets go.k6.io/k6 v1, and until it gets updated, you're stuck choosing between k6 v2's improved architecture or the ability to measure streaming metrics properly. So the companion repo does the pragmatic thing: it tests the /chat/complete endpoint instead of the /chat streaming endpoint, using k6's built-in http module. No custom binary, no extensions, just standard k6. The tradeoff is you lose true TTFT measurement, because /chat/complete waits for the full response before returning. What you get instead is end-to-end latency, which is still useful it tells you if the system is slow, just not why it's slow. Here's what the test looks like: JavaScript import http from 'k6/http'; import { Trend, Counter } from 'k6/metrics'; import { check } from 'k6'; const totalDuration = new Trend('total_duration_ms', true); const tokensPerSecond = new Trend('tokens_per_second'); const BASE_URL = __ENV.RAG_APP_URL || 'http://localhost:8080'; export const options = { scenarios: { rag_chat: { executor: 'ramping-vus', stages: [ { duration: '30s', target: 10 }, { duration: '1m', target: 10 }, { duration: '30s', target: 0 }, ], }, }, thresholds: { http_req_duration: ['p(95)<6000'], total_duration_ms: ['p(95)<6000'], }, }; export default function () { const startTime = Date.now(); const res = http.post( `${BASE_URL}/chat/complete`, JSON.stringify({ query: 'How do I run JMeter in non-GUI mode?' }), { headers: { 'Content-Type': 'application/json' }, timeout: '30s', }, ); const duration = Date.now() - startTime; check(res, { 'status 200': (r) => r.status === 200, 'has answer': (r) => JSON.parse(r.body).answer !== undefined, }); totalDuration.add(duration); // Rough tokens/sec estimate from word count const words = JSON.parse(res.body).answer.trim().split(/\s+/).length; tokensPerSecond.add((words / duration) * 1000); } The test ramps from 0 to 10 virtual users over 30 seconds, holds for a minute, then ramps back down. Thresholds are set at p95 < 6000ms for both http_req_duration and the custom total_duration_ms metric. When should you switch back to SSE? Watch the xk6-sse repo. Once it adds k6 v2 support, swap the endpoint from /chat/complete to /chat, add the SSE extension to your Dockerfile, and you'll get true TTFT measurement. Until then, this is the most pragmatic path forward: standard k6, no custom builds, just with the caveat that you're measuring end-to-end latency rather than streaming behavior. The companion repo includes both endpoints in the Express app so you can switch when you're ready: EndpointResponseStatusPOST /chatSSE streamReady for when xk6-sse supports k6 v2POST /chat/completeFull JSONUsed by k6 and DeepEval today Wiring Both Gates Into CI/CD Once both tests run locally, wiring them into GitHub Actions is mostly plumbing: start the app, wait for it to be healthy, run the k6 gate, run the DeepEval gate, both in parallel since they're independent. YAML name: RAG CI on: [pull_request] jobs: performance-gate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Write app env file run: | cat > app/.env << EOF GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY } GEMINI_MODEL=gemini-3.5-flash FILE_SEARCH_STORE_NAME=${{ secrets.FILE_SEARCH_STORE_NAME } PORT=8080 EOF - name: Start RAG app run: docker compose up -d --build app - name: Wait for health run: | timeout 60 bash -c 'until curl -f http://localhost:8080/health; do sleep 2; done' - name: Run k6 load test run: docker compose --profile perf run --rm k6 quality-gate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Write app env file run: | cat > app/.env << EOF GEMINI_API_KEY=${{ secrets.GEMINI_API_KEY } GEMINI_MODEL=gemini-3.5-flash FILE_SEARCH_STORE_NAME=${{ secrets.FILE_SEARCH_STORE_NAME } PORT=8080 EOF - name: Start RAG app run: docker compose up -d --build app - name: Wait for health run: | timeout 60 bash -c 'until curl -f http://localhost:8080/health; do sleep 2; done' - name: Run DeepEval tests env: GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY } run: docker compose --profile quality run --rm deepeval Both jobs run on every pull request. A PR that slows down response time and a PR that quietly makes the model hallucinate get caught the same way, before either reaches a reviewer's eyeballs, let alone production. You'll need to add two secrets to your GitHub repo before the workflow will pass: SecretValueGEMINI_API_KEYYour Gemini API key from https://aistudio.google.com/apikeyFILE_SEARCH_STORE_NAMEThe store name from setup-store.js (format: fileSearchStores/your-store-id) Setting SLOs I'm deliberately not giving you one universal latency number to target. I've seen guidance ranging from sub-second targets for chat-style RAG apps to 3-5 second budgets for more complex document analysis, and the right number for you depends entirely on your retrieval backend, your model, and what your users are actually doing. Run the load test against your own baseline first, then set thresholds off that baseline, not off a number from a blog post (including this one). The example repo uses p95 < 6000ms as a starting point because that's what the test Gemini File Search RAG app achieves at 10 concurrent users with gemini-3.5-flash. Your mileage will vary dramatically based on: Model choice (flash vs pro, size of context window actually used) Retrieval backend (vector DB query time, number of chunks retrieved) Document size and complexity Network latency to your LLM provider What you should track regardless of the exact number: p95 and p99 latency, not just the median. The tail experience is what users complain about. Latency at your expected concurrency, not at 1 user. RAG apps often degrade non-linearly under load because of retrieval bottlenecks. Faithfulness and answer relevancy trending over time, not just pass/fail on one run. A metric that's consistently 0.90 dropping to 0.78 is a signal even if both pass the 0.75 threshold. Wrap-Up RAG performance testing is really two disciplines wearing one trench coat: classic load testing with LLM-aware metrics, and LLM-as-judge quality scoring that classic load testing tools were never built to do. Run them both, gate on both, and you'll catch the regressions that a speed-only test walks right past. The current state of tooling isn't perfect; you can't measure TTFT with k6 v2 without writing your own SSE client, and LLM-as-judge scoring has its own consistency quirks, but it's good enough to catch regressions before production, which is the whole point of a CI/CD gate. Head to the companion GitHub repo for the full working app, k6 script, DeepEval tests, Docker Compose setup, and GitHub Actions workflow you can clone and run locally in under five minutes. Happy testing! Have you run into hallucination regressions that a pure load test missed? I'd like to hear how you caught them; reply on X or open an issue on the companion repo.

By NaveenKumar Namachivayam DZone Core CORE
Building Reliable Async Processing Pipelines Using Temporal
Building Reliable Async Processing Pipelines Using Temporal

Asynchronous processing pipelines are a cornerstone of modern distributed systems, but wiring them together reliably can be complex. A typical pipeline built with queues or message brokers requires custom retry logic, dead-letter queues, cron recovery jobs, and database status flags to ensure every step eventually succeeds. Temporal replaces this heavy plumbing with durable workflows. In a Temporal workflow, the business logic of the pipeline is written as ordinary sequential code, yet it executes reliably across failures. The platform persists every state transition and step so that if a worker crashes or a network blip occurs, execution resumes exactly where it left off. This durability makes Temporal a natural fit for async pipelines: instead of scattered consumers and convoluted retry code, the pipeline steps read like simple procedure calls. For example, consider a workflow that processes a batch of items by cleaning and storing each one. In Temporal’s Java SDK, this might look like: Java public class PipelineWorkflowImpl implements PipelineWorkflow { @Override public List<String> run(List<String> items) { PipelineActivities activities = Workflow.newActivityStub(PipelineActivities.class); List<String> results = new ArrayList<>(); for (String item : items) { // clean and store each item String cleaned = activities.clean(item); results.add(activities.store(cleaned)); } return results; } } Here PipelineActivities is an interface with clean() and store() methods implemented as activities. The workflow invokes them sequentially inside a loop. Although it looks like ordinary code, Temporal records each activity invocation and its result durably. If the worker goes down after cleaning the first item, the workflow will automatically resume and continue processing the next item when recovery happens – without redoing the steps that have already been completed. Because workflows are executed atomically by the Temporal engine, developers no longer need to manage external state for progress or handle duplication. Temporal’s built‑in retry and timeout mechanisms remove a lot of boilerplate. Each activity can be configured with a retry policy so that transient failures are retried automatically. For instance, one can create an activity stub with options like: Java ActivityOptions options = ActivityOptions.newBuilder() .setStartToCloseTimeout(Duration.ofSeconds(30)) .setRetryOptions(RetryOptions.newBuilder() .setMaximumAttempts(5).build()) .build(); MyActivities activities = Workflow.newActivityStub(MyActivities.class, options); Any exception in the process() method called via this stub will trigger an automatic retry (up to 5 times) with backoff, as specified. This eliminates writing manual retry loops. In fact, Temporal emphasizes “automatic retries with zero boilerplate.” Under the hood, the workflow code is re‑played after a failure to resume exactly at the point of the failed activity; previous successful activity results remain in state, preventing duplicate processing or reordering issues. Idempotency is important: since activity calls may happen more than once (because of retries or once‑only delivery semantics), activity implementations should avoid side effects or perform them in an idempotent way. Temporal’s documentation notes that it provides at-least-once guarantees for activities and suggests using idempotency patterns to avoid unintended side effects. In practice, this means each activity should be designed so that retrying it does not corrupt data or create duplicates. Because the workflow ensures the overall business logic runs only once, one effectively achieves an “exactly-once” effect for the end-to-end pipeline, even though individual tasks may run multiple times internally. Error handling in pipelines often requires special orchestration. Temporal allows workflows to catch exceptions and perform compensating actions. For example, if a step fails, the workflow code can catch that error and invoke cleanup activities for previously completed steps. This is effectively implementing a saga pattern. As a Temporal blog explains, workflows can maintain a stack of “compensations” so that if a downstream step fails, all prior steps can be rolled back. In code, this might look like building a list of cleanup lambdas and invoking them in reverse order on failure. This approach restores consistency without the complexity of distributed transactions. (The blog illustrates this with an account creation saga that rolls back user, address, and client profile creation if any step fails.) In pipeline terms, such compensation could delete database entries, refund charges, or revert state changes that should not stand after an error. Temporal workflows also support concurrency patterns useful in pipelines. Multiple activities can be invoked in parallel (for example, via Async.function or Promise.allOf() in the Java SDK) if tasks don’t have dependencies. This lets the pipeline exploit parallelism where possible. In the code above, items were processed one by one for simplicity, but a workflow could instead fire off many clean() calls at once and wait for all results before storing them. Even with parallel branches, the durable execution guarantee holds: the workflow will wait for all forks to complete or time out, and failures in any branch can be handled gracefully in the main workflow code. Because Temporal provides a full history of every workflow execution, observability is greatly improved. Operators can see each step of the pipeline, inspect where failures occurred, and even replay past executions for debugging. This transparency means pipelines built with Temporal are easier to monitor and diagnose than message-queue-based systems, where tracing a message through many services can be difficult. The Temporal Web UI or APIs expose this history, turning a “black box” pipeline into a self-documenting process. All of these features contribute to resilient pipelines. When a worker process unexpectedly restarts, or a service call fails, the Temporal engine takes care of recovery. The developer’s pipeline code can remain clean and linear: for instance, charging a customer, reserving inventory, and sending confirmation can be written as sequential await calls, yet each step is automatically retried and persisted. There is no need to maintain manual error tables or implement dead-letter queues – if the final shipping step fails after payment succeeds, the workflow won’t forget that fact. Instead, it can catch the failure and trigger a refund or compensation logic. Temporal “collapses” the usual async pipeline complexity into a straightforward workflow execution. In summary, building async pipelines with Temporal means delegating orchestration and fault tolerance to the platform. The developer writes a workflow method that looks like normal code with activity calls; the Temporal engine records each call, retries on errors, and continues after crashes, so the pipeline runs to completion exactly once. This durable execution model, combined with declarative retries and compensation patterns, delivers highly reliable pipelines without excessive custom infrastructure. For teams needing robust pipelines that survive service failures and network issues, Temporal provides a powerful foundation that simplifies development and maintenance.

By Akhil Madineni
Goodbye, Skeleton Keys: Why Machine Identity Broke IAM, and What SPIFFE Is Doing About It
Goodbye, Skeleton Keys: Why Machine Identity Broke IAM, and What SPIFFE Is Doing About It

Cloudflare published its own forensic timeline of the Salesloft Drift breach down to the minute, and it's worth sitting with the detail for a second. At 11:51 on August 9, 2025, an actor researchers track as GRUB1 tried to validate a stolen Cloudflare API token against the Salesforce API using TruffleHog's user-agent string — a tool built for finding leaked secrets, repurposed here to confirm one actually worked. That attempt failed. At 22:14, it didn't. GRUB1 walked into Cloudflare's Salesforce tenant using a credential that belonged to the Salesloft Drift integration, no exploit required, no privilege escalation needed — just a token that had been sitting there, valid, with no expiry pressure and no second factor to clear. Cloudflare wasn't an outlier. Google's Threat Intelligence Group eventually counted more than 700 organizations hit through that same OAuth token theft, including Google itself, Palo Alto Networks, and Proofpoint. I keep coming back to that incident in conversations with platform teams, because it's the cleanest illustration I've seen of a problem that's now bigger than any single breach: we built identity and access management for humans, and then we quietly let it sprawl across a population of machines that outnumber humans by a ratio nobody fully agrees on, but everyone agrees is large. CyberArk's 2025 Identity Security Landscape study puts machine identities at more than 80 to 1 against human accounts in the average enterprise. Other measurements land lower or higher depending on methodology — the point isn't the exact multiple, it's that every credible number has been climbing for three straight years, and AI agents are the fastest-growing slice of it. The Bottom Turtle There's an old explanation of the universe — turtles all the way down — that the SPIFFE community borrowed for exactly this problem, sometimes literally titling their own documentation "Solving the Bottom Turtle." The question it's pointing at is uncomfortable: when service A needs to prove its identity to service B, what's the root of that trust? For most organizations through the 2010s, the honest answer was "a string." An API key baked into a config file. A service account password rotated, if you were disciplined, once a quarter. A shared secret copied from a wiki page that three former employees probably still remember. None of that was a deliberate architecture decision. It was what happened by default when nobody designed for machine-scale identity, because for most of computing history, nobody had to. SPIFFE — the Secure Production Identity Framework for Everyone — came out of the people who hit that wall first, at the scale where it actually hurts: engineers from Google, Netflix, Pinterest, and Amazon, along with a startup called Scytale that's since been folded into Hewlett Packard Enterprise, pooling their separately built internal solutions into a shared open standard. SPIRE is the production-grade runtime that implements it, and both are now graduated projects under the Cloud Native Computing Foundation — the same governance tier Kubernetes itself holds. That's not a vanity badge. It signals that the CNCF's technical oversight committee considers the project's adoption and maturity broad enough to bet production infrastructure on, which is precisely what Uber, Block (formerly Square), Bloomberg, ByteDance, and the financial services firm Wise have done, each presenting their own deployment at SPIFFE community events over the past several years. Wise's case is the one I find most persuasive for regulated industries specifically: they adopted SPIRE to establish trust between systems operating across different regulatory jurisdictions, replacing shared secrets with something an auditor could actually verify cryptographically rather than take on faith. What an SVID Actually Buys You Strip away the acronyms, and the mechanism is fairly elegant. A SPIRE Agent runs on every node. When a workload starts up, the agent doesn't ask it to present a password — it interrogates the environment the workload is running in: which Kubernetes service account launched it, which container image hash it's running, which cloud instance metadata applies. That process is called attestation, and it's the part that matters most, because it ties identity to something an attacker can't simply copy out of a config file. If attestation succeeds, the agent requests a SPIFFE Verifiable Identity Document — an SVID — from the SPIRE Server: either an X.509 certificate for mutual TLS or a JWT for API-style calls, both scoped to a narrow lifetime, often measured in minutes rather than months. That lifetime is the entire point. One practitioner walkthrough I'd recommend to any platform engineer puts the contrast plainly: steal a static API key and an attacker holds working access until someone notices and rotates it, a process that in real incident response routinely takes days. Steal an SVID, and the credential is already approaching its own expiration before anyone needs to act — the damage window is bounded by cryptographic TTL instead of by how fast your detection pipeline happens to be that week. Compare that against the Cloudflare timeline above, where the stolen token had no built-in clock running against the attacker at all. Production deployments increasingly don't ask application code to deal with any of this directly. Service meshes absorb it at the infrastructure layer instead: Istio issues SPIFFE-compliant identities to every workload by default through its own internal certificate authority, and organizations that want centralized governance across mesh and non-mesh workloads alike can point Istio at an external SPIRE deployment instead, unifying the audit trail. Envoy proxies fetch SVIDs straight from a local SPIRE Agent through its Secret Discovery Service, which means mutual TLS between two services can be enforced with zero changes to either service's application code — the identity lives in the sidecar, not the business logic. Where Cloud IAM Already Got This Half Right None of this is unique to the open-source SPIFFE world, and it's worth being fair to the cloud providers here, because they solved an adjacent piece of the same problem years ago for one specific case: a workload calling its own cloud provider's APIs. AWS's IAM Roles for Service Accounts — IRSA — lets a pod running in EKS exchange a short-lived, Kubernetes-issued OIDC token for temporary AWS credentials, instead of mounting a static access key into the container image. Google Cloud's Workload Identity Federation and Azure's federated credentials do the structural equivalent for their own platforms. All three share the same underlying trick: trade a long-lived secret for a freshly minted, narrowly-scoped token, issued just-in-time, federated through an OIDC trust relationship rather than copy-pasted by a human. The gap is what happens the moment a workload needs to talk to something that isn't its home cloud's API — another service on the same team's mesh, a partner's system in a different cloud, a vendor integration that predates anyone's identity strategy. AWS IAM has no opinion about a request arriving from GCP. That's the seam SPIFFE is built to close: a single SPIFFE ID and trust model that spans Kubernetes, VMs, multiple clouds, and on-prem hardware at once, with authorization policies written against that one identity rather than against whichever cloud-specific construct happens to apply this week. You can, and increasingly should, run both layers together — IRSA or Workload Identity Federation for the “talking to my own cloud” case, SPIFFE/SPIRE for everything else, federated through each cloud's OIDC provider so the two systems trust the same root rather than operating as separate, unrelated islands. Workload starts | v SPIRE Agent --attests workload--> (checks: k8s service account, | container image hash, node identity) | attestation OK v SPIRE Server --issues--> SVID (X.509 cert or JWT, TTL: minutes) | +----> mTLS to peer workload (via Envoy/Istio sidecar, SPIFFE ID in cert SAN) | +----> OIDC Federation --> Cloud IAM (AWS STS / GCP WIF) --> short-lived cloud creds | +----> SVID expires automatically; re-attestation required for renewal The Part Agentic AI Just Made Worse Everything above was already a hard problem before AI agents entered the picture, and the agents have not been gentle with it. Gartner flagged non-human identity management as a top 2025 strategic trend specifically because of agentic AI's growth curve, and OWASP responded with a dedicated Non-Human Identity Top 10 the same year — an acknowledgment that neither traditional application security tooling nor human-centric IAM processes were built with credentials that never sleep, never log in interactively, and frequently outlive the project that created them. The npm worm campaigns that tore through the back half of 2025 made the failure mode concrete rather than theoretical: forensic write-ups of the Shai-Hulud malware describe it actively harvesting environment variables and any cloud credentials exposed through instance metadata services on infected build runners — precisely the long-lived, broad-scope keys that IRSA and Workload Identity Federation exist to eliminate, sitting unprotected because someone, somewhere, found it easier to bake in a static key than to wire up federation. And then there's the harder case, the one that should concern anyone running agentic systems in production: Anthropic's account of the GTG-1002 espionage campaign in late 2025 described a threat actor manipulating an AI coding agent into autonomously executing the bulk of an intrusion across roughly thirty targets. An agent acting with that kind of autonomy needs some identity to operate under. If that identity is a copied human credential or a static service account with standing privilege — the skeleton-key pattern this whole piece has been arguing against — then a manipulated agent inherits every door that credential opens, instantly, at whatever speed the agent can issue requests. If instead it's a narrowly attested, short-lived SVID scoped to exactly the tools that the agent's task requires, the same manipulation still happens, but the blast radius it can reach is bounded by design rather than by luck. Where This Actually Goes in Practice Nobody serious is suggesting a rip-and-replace migration, and the practitioners who've done this well consistently describe a phased rollout instead: stand up SPIRE on Kubernetes first, prove mTLS between two or three high-value internal services, then move to eliminating the cloud credential files with the broadest blast radius — typically the workloads touching object storage or managed databases — before tackling legacy VMs and anything that predates the cluster entirely. None of it requires abandoning Vault, AWS Secrets Manager, or whatever secrets store already exists; SPIFFE is narrower than that, it specifically removes the class of secret used purely to prove "I am workload X," and leaves genuine application secrets — database passwords for systems that haven't adopted modern identity, third-party API keys — to whatever vault you're already running, just with a shrinking footprint over time. The IETF formalized a working group for Workload Identity in Multi-System Environments in 2024, which tells you where the standards body sees this heading: not as a niche Kubernetes pattern, but as infrastructure plumbing on the same tier as TLS itself. My honest read, watching this mature over the past two years: a decade from now, handing a workload a static, long-lived credential is going to look the way handing an employee a permanent admin password without MFA looks today — technically functional, and a decision nobody will be able to defend after the fact.

By Igboanugo David Ugochukwu DZone Core CORE
Service Industry Evolution: Beyond 99.9% Uptime With Evolving Technology
Service Industry Evolution: Beyond 99.9% Uptime With Evolving Technology

For years, service organizations measured operational efficiency through response time. A machine failed, a ticket dropped, a technician arrived on-site, and the diagnosis and repair resolved the issue. Industries dependent on physical assets accepted this framework because they believed that it was not possible to avoid downtime. The benchmark for operational excellence depended on how quickly teams reacted after disruption occurred. That definition of service reliability has changed dramatically. Across industries such as ATM infrastructure, elevator systems, industrial manufacturing, HVAC networks, utilities, and connected buildings, uptime has evolved from a technical KPI into a direct business expectation. A malfunctioning elevator inside a commercial tower immediately affects tenant experience. An unavailable ATM network during a transaction spike escalates into a customer-service issue within minutes. In sectors where Service Level Agreements (SLAs) define accountability, even short-lived disruption can simultaneously create financial penalties, reputational damage, and customer churn. This growing pressure explains why organizations are restructuring service operations around predictive intelligence, telemetry ecosystems, and AI-driven operational visibility. Businesses targeting 99.9% uptime, commonly referred to as “three nines” availability, now operate within extremely narrow tolerance margins. Operationally, that benchmark allows for less than nine hours of annual downtime across distributed infrastructure environments involving connected assets, IoT systems, APIs, cloud platforms, and field-service networks. Connected Assets Are Reshaping Service Delivery The most significant transformation inside the service industry is happening beyond customer-facing applications. Machines themselves are becoming active participants in operational decision-making. Modern industrial assets continuously transmit telemetry related to vibration intensity, thermal behavior, airflow fluctuations, voltage variation, load cycles, and component stress. Earlier maintenance environments depended heavily on scheduled inspections and manual servicing intervals. Predictive ecosystems now analyze live operational behavior continuously, allowing organizations to identify abnormal machine patterns before a visible breakdown occurs. Large elevator manufacturers increasingly rely on telemetry-driven systems that can identify brake-pressure instability and motor stress, even before shutdown occurs inside high-footfall commercial environments. Similarly, ATM infrastructure providers now use transaction telemetry and demand analytics to forecast cash replenishment cycles proactively during high-volume periods. According to McKinsey & Company, predictive maintenance typically reduces machine downtime by 30 to 50% and increases machine life by 20 to 40%. IBM has also estimated that such predictive maintenance frameworks can improve labor productivity while helping organizations reduce downtime and improve asset reliability. Why Predictive Maintenance Is Replacing Reactive Service Models Traditional field-service environments created inefficiencies that organizations quietly accepted for years. Once a machine failed, there was a simultaneous trigger effect on multiple disconnected workflows. Service teams logged tickets, identified technicians, diagnosed faults, verified spare-part availability, and scheduled follow-up visits. Very often, engineers reached the site without the required replacement component, forcing additional visits and extending downtime unnecessarily. Predictive service ecosystems reduce that operational friction. Modern AI-enabled maintenance systems increasingly integrate telemetry platforms directly with workforce management tools, inventory systems, and service histories. Instead of merely identifying faults, these environments support operational decision-making before engineers physically engage with the asset. operational eventconventional workflowpredictive ai-led workflow ATM cash depletion Shortage identified after customer disruption AI forecasts replenishment needs proactively Elevator motor instability Technician dispatched after operational failure Telemetry predicts degradation before shutdown HVAC compressor fluctuation Complaint-driven escalation Continuous monitoring detects abnormal pressure patterns Industrial equipment fault Manual diagnosis during site visit AI identifies component failure in advance Modern industrial-service providers use AI-led technician orchestration systems that evaluate technician expertise, asset familiarity, certification levels, and spare-part availability before dispatch approval occurs. The objective is not faster repair cycles anymore. Organizations are now trying to prevent customer-facing disruption before it begins. Observability Is Replacing Conventional Monitoring Earlier, the designs of monitoring systems ensured they could primarily identify if the infrastructure was functioning properly. Modern service ecosystems require deeper operational visibility because enterprises no longer operate in isolated environments. Most organizations now manage interconnected systems spanning IoT networks, enterprise applications, APIs, operational technology environments, cloud platforms, and legacy infrastructure. In such environments, isolated alerts provide limited value because operational disruption often emerges from cascading dependencies rather than a single infrastructure failure. Observability platforms address this challenge by correlating telemetry, metrics, traces, logs, and behavioral anomalies into unified operational intelligence layers. Instead of simply reporting that a service has failed, these systems analyze why the disruption occurred, which systems contributed to it, and how the issue may spread across dependent environments. Platforms such as Datadog, New Relic, and Dynatrace have become central to enterprises attempting to maintain high-availability infrastructure environments. Agentic Observability Is Introducing Autonomous Operations The latest evolution in observability is moving beyond monitoring toward autonomous operational investigation. Dynatrace’s Davis AI engine, for example, maps infrastructure dependencies continuously across cloud and on-premises ecosystems. Instead of overwhelming operations teams with fragmented alerts, the platform isolates probable root causes and predicts which infrastructure layers may destabilize next. Several enterprises are now moving toward what technology leaders describe as “agentic observability,” where AI systems autonomously investigate operational anomalies, correlate dependencies, recommend corrective action, and reduce the likelihood of SLA breaches before customers experience visible disruption. External observability platforms such as Site24x7 and UptimeRobot further strengthen operational assurance by validating customer-facing service availability across regions continuously. According to Gartner, as predictive root-cause analysis becomes more mature across enterprise infrastructure ecosystems, enterprises adopting AI-led operational intelligence frameworks help to reduce incident-resolution timelines. Why Incident Response Speed Has Become a Competitive Differentiator Even the most advanced predictive ecosystems cannot eliminate every operational incident. What increasingly separates high-performing service organizations from reactive operators is the speed and coordination of their response environments once disruption begins. Modern incident-management platforms are now heavily automated. Enterprises increasingly use AI-enabled response systems that identify affected services, create incident channels automatically, notify relevant engineers, and coordinate escalation processes in real time. Several operational capabilities now determine how effectively organizations respond to high-severity incidents in modern uptime environments. These include: Faster escalation reduces Mean Time to Resolution (MTTR) and minimizes SLA impact.Automated response coordination that prevents communication delays during outagesIntelligent alert routing to ensure that the right teams engage immediately.Slack-native response environments to improve collaboration across distributed teams.AI-driven incident workflows that reduce operational confusion during high-severity failures. Platforms such as PagerDuty, Rootly, FireHydrant, and incident.io are helping enterprises streamline incident coordination significantly across distributed operational environments. Uptime Architecture Is Becoming a Strategic Business Decision Many enterprises still approach disaster recovery as a secondary IT function rather than a central business-continuity strategy. That approach is becoming increasingly risky in sectors where even brief disruption can affect customer trust and SLA commitments. Modern uptime environments now depend heavily on resilience architecture designed to absorb disruption without affecting customer operations. Enterprises are therefore investing aggressively in multi-region infrastructure, failover environments, and redundancy frameworks intended to eliminate single points of failure. Several financial services firms and industrial infrastructure providers now operate active-active environments where workloads distribute simultaneously across multiple operational regions. If one region experiences instability, remaining infrastructure absorbs traffic automatically with minimal disruption. Recovery-as-Code Is Changing Disaster Recovery Planning Other organizations rely on active-passive models where secondary standby environments activate rapidly during outages. Large enterprises have also started adopting hybrid multi-cloud strategies involving combinations of AWS, Azure, and Google Cloud to reduce dependency on a single provider. Disaster recovery itself has evolved significantly over the last few years. Earlier recovery frameworks depended heavily on manual restoration processes, isolated backups, and infrastructure rebuilding exercises that often stretched across several hours. Modern recovery environments increasingly rely on software-driven replication and automated restoration systems. Infrastructure-as-Code frameworks such as Terraform and Pulumi now allow enterprises to recreate infrastructure environments programmatically. Platforms such as AWS Elastic Disaster Recovery and ControlMonkey are helping organizations replicate workloads, restore cloud configurations, and improve recovery consistency during failover scenarios. Enterprises increasingly design systems capable of functioning effectively even while failure conditions occur. Why Data Availability Has Become as Critical as Infrastructure Availability As service ecosystems become more dependent on real-time operational intelligence, enterprises are also discovering that uptime extends far beyond infrastructure resilience alone. Data availability now plays a key role in maintaining service continuity. In asset-intensive industries, operational environments depend heavily on uninterrupted access to telemetry streams, maintenance histories, customer records, compliance data, and software supply chains. A ransomware incident or corrupted recovery environment can affect service operations as severely as infrastructure failure itself. This explains why organizations are investing heavily in platforms such as Cohesity and Rubrik, which focus on rapid recovery, immutable backup environments, and zero-trust data resilience strategies. Similarly, JFrog has increasingly positioned software supply-chain availability as a critical reliability layer for enterprises managing continuous deployment environments. Chaos Engineering Is Moving into the Mainstream For years, organizations assumed failover systems would function correctly during outages simply because backup infrastructure existed architecturally. Recovery environments often failed under real-world pressure because teams had never tested them comprehensively. Chaos engineering emerged as a direct response to that gap. Platforms such as Gremlin and LitmusChaos deliberately simulate disruption scenarios inside controlled environments. Teams intentionally interrupt APIs, overload infrastructure layers, disable databases, and simulate cloud-region failures to evaluate whether resilience mechanisms function correctly under operational stress. Organizations operating large-scale digital infrastructure increasingly use controlled-failure testing to understand how systems behave during real outages rather than relying solely on theoretical resilience assumptions. The Operational Disciplines Separating Mature Reliability Teams from Reactive Service Organizations Organizations that consistently maintain high uptime rarely depend on infrastructure investment alone. Most high-performing service environments combine technology modernization with disciplined operational governance frameworks designed to reduce preventable disruption. Error Budgets Are Forcing Teams to Balance Innovation with Stability Modern Site Reliability Engineering (SRE) environments no longer chase unrealistic zero-downtime goals. Organizations define acceptable downtime thresholds and pause feature deployment if operational instability crosses predefined limits. Progressive Deployment Models Are Reducing Large-Scale Service Failures Many enterprises now use canary deployment strategies that release updates gradually across smaller user environments before full-scale deployment occurs. This allows organizations to isolate instability before broader infrastructure disruption affects customers. Blameless Post-Mortems Are Improving Long-Term Operational Maturity Several organizations have shifted away from punitive outage-review cultures because delayed escalation often worsens downtime impact. Blameless review frameworks encourage teams to identify missing safeguards and process weaknesses more transparently. Change-Freeze Windows Are Becoming Standard Across High-Risk Operations Industries operating under strict SLA commitments increasingly enforce no-change windows during high-volume transaction periods, financial closings, infrastructure migrations, or critical production cycles. Incident Command Structures Are Accelerating Crisis Coordination High-availability environments increasingly rely on predefined incident-response hierarchies involving technical leads, communication owners, escalation managers, and operational coordinators. Enterprises that consistently maintain high uptime typically treat governance maturity as seriously as infrastructure resilience. Operational discipline often determines whether advanced technology investments really deliver measurable reliability outcomes. Technologies Driving Predictive SLA Management The service industry is moving steadily toward operational environments where organizations can forecast SLA risk before customer disruption occurs. This transition is accelerating because enterprises now recognize that service continuity directly influences revenue stability, retention, and operational trust. Telemetry Analytics Is Helping Enterprises Detect Early-Stage Operational Instability Connected infrastructure environments continuously generate operational intelligence related to machine performance, infrastructure stress, transaction behavior, and service degradation patterns. AI-Led Anomaly Detection Is Improving Failure Prediction Accuracy Platforms such as Dynatrace, IBM Maximo Application Suite, and C3 AI now combine anomaly detection with machine-learning models capable of forecasting operational degradation across industrial systems. SLA Risk Scoring Models Are Changing Operational Decision-Making Solutions such as Sirion and Nobl9 increasingly combine telemetry analytics, infrastructure dependencies, incident history, and contractual thresholds to generate SLA breach probability scores. Predictive environments can now identify rising compliance risks a week to two before a potential SLA breach occurs. Workforce Orchestration Systems Are Improving First-Time Resolution Rates Modern field-service environments increasingly integrate AI-led dispatch intelligence with technician certification data, inventory systems, and asset history. This allows organizations to assign the most suitable technician with the right replacement components before service disruption expands further. The broader transition toward predictive SLA intelligence reflects a larger shift across the service industry. Organizations are gradually moving away from response-driven operations toward environments capable of identifying operational instability before customers experience visible disruption. The Future of Service Operations Will Depend on Prevention The digital transformation of the service industry extends far beyond automation or cloud migration. Organizations leading this transition increasingly combine connected telemetry ecosystems, AI-driven observability, predictive asset intelligence, resilient infrastructure architecture, workforce orchestration platforms, and operational governance frameworks into unified service environments designed around prevention rather than response. Historically, service organizations optimized for repair efficiency. The next generation of operational leaders is optimizing for disruption avoidance. Predictive intelligence, connected telemetry, and AI-led service orchestration are steadily becoming foundational requirements for enterprises operating large-scale asset-driven service ecosystems. Over the next few years, the competitive gap between service organizations will no longer depend solely on who resolves incidents faster. It will depend on which enterprises can predict operational instability earlier, coordinate response systems more intelligently, and prevent disruption before customers experience its impact. In industries where uptime increasingly shapes customer trust, contractual performance, and operational continuity simultaneously, prevention is steadily becoming the new benchmark for service excellence.

By Abhishek Sharma
Top 10 Best Places to Prepare for Your Next Data Engineer Interview
Top 10 Best Places to Prepare for Your Next Data Engineer Interview

Landing a data engineering role means clearing a gauntlet that no other software discipline has to face all at once: airtight SQL, production-grade Python, data modeling instincts, distributed-compute fluency (Spark, warehouses, ETL), and system design that has to survive real data volume. Generic coding prep barely scratches the surface, and "just grind LeetCode" advice falls apart the moment an interviewer asks you to model a slowly changing dimension or reason about a skewed join. So we did the work. We evaluated the resources data engineers actually use, judged on five things that matter: relevance to the DE interview loop, depth of practice, realism of the questions, feedback quality, and price. Below is the ranked list. A quick note on methodology: this ranking favors resources that target the data engineering loop specifically, not generic algorithm grinding. That bias is intentional, and it is why the order may surprise you. 1. DataDriven.io Most "interview prep" platforms were built for generic SWE roles and bolt on a SQL section as an afterthought. This one was built from the ground up for the data engineering loop. The catchphrase you will hear repeated in DE communities is that DataDriven.io is LeetCode for data engineers, and it fits: instead of inverting binary trees, you are writing window functions against realistic schemas, designing star schemas, debugging an ETL transform, and reasoning about partitioning, all in an in-browser SQL and Python sandbox that runs your query against real data and tells you exactly where it broke. It is also the rare place where the whole product is built for the job rather than adjacent to it, which is why datadriven.io is great for data engineer interview prep specifically: SQL practice that ramps to multi-CTE analytics, a deep set of Python practice problems, plus data modeling, dimensional modeling, PySpark, and system-design tracks, with execution-based feedback and a difficulty curve that reaches the staff-level questions that actually separate offers from rejections. Verdict: The most targeted, realistic data engineering interview practice available today. Earns the top spot. 2. "Cracking the Coding Interview" (the book, by Gayle Laakmann McDowell) A deserved classic, and intentionally a book rather than a website. CTCI is still the best single artifact for understanding how technical interviews are actually structured: how the conversation flows, how to think out loud so the interviewer can follow your reasoning, how to recover when you get stuck, and how to handle the behavioral and negotiation segments that strong candidates routinely fumble. Most people lose offers not because they could not solve the problem but because they could not show their work, and this book is the canonical fix for that. Where it falls short for our purposes is scope. It will not teach you windowed SQL, slowly changing dimensions, or how to design a lakehouse, and its algorithm focus skews toward generalist software roles rather than the data engineering loop. The data structures and big-O chapters are still worth a pass because algorithm screens do show up, but treat them as a refresher, not your main event. Read CTCI once early in your prep to fix your interview mechanics, internalize the communication patterns, then spend the rest of your time on hands-on, domain-specific platforms. Verdict: Essential reading for interview mechanics; not a substitute for domain practice. 3. "Designing Data-Intensive Applications" (the book, by Martin Kleppmann) If CTCI teaches you how to interview, "DDIA" teaches you what a data engineer is actually supposed to know. Replication, partitioning, consistency models, batch versus stream processing, storage engine internals, the failure modes of distributed systems: this is the conceptual backbone of nearly every data engineering system design round. When an interviewer asks why you would choose a log-structured merge tree over a B-tree, or how you would keep two datastores in sync without losing events, the answers live in these pages. It is dense, and it is emphatically not an interview drill book. You will not find practice questions, and you cannot cram it the night before. What it gives you instead is judgment: the candidate who has internalized DDIA answers "how would you design this pipeline" with the calm of someone who has already thought through the tradeoffs, names the failure cases before being prompted, and explains why a choice holds up under real data volume. Read it slowly over weeks, ideally early in your prep, and pair it with a hands-on platform so the concepts attach to actual queries and schemas rather than floating as theory. Verdict: The definitive conceptual reference. Read it slowly, alongside real practice. 4. LeetCode The default destination, and it earns its spot for one practical reason: the Database problem set is sizable, the algorithm catalog is enormous, and the platform's brand means a large share of companies still pull their initial coding screen straight from it. If your target company is known to run a generic algorithm round before the data-specific rounds, you need exposure here, and the sheer volume of problems plus community discussion means you will rarely be surprised by a pattern you have never seen. The catch for data engineers is that LeetCode was built for the algorithm interview, not the DE loop. Its SQL section is genuinely solid but secondary; the questions are puzzle-shaped rather than drawn from real schemas, and you will not find data modeling, ETL design, dimensional modeling, or Spark anywhere on the platform. There is also a real failure mode here: candidates over-invest in LeetCode because it is comfortable and gamified, then walk into a DE loop under-practiced on the things that actually decide it. Use it deliberately to clear the algorithm gate and to keep your raw coding sharp, then move the bulk of your hours to resources that target data engineering directly. Verdict: Necessary for the algorithm screen; thin for the data-engineering-specific rounds. 5. HackerRank HackerRank is where a surprising number of companies host their take-home and timed online assessments, so practicing in its environment carries a payoff most resources cannot offer: you get comfortable with the exact editor, the exact test-case runner, and the exact time-pressure UI you may actually be scored in. For an assessment you cannot retake, that familiarity is worth real points, because fighting an unfamiliar interface while the clock runs is a self-inflicted way to lose. Its SQL and problem-solving tracks are beginner-friendly, well-structured, and free to work through. The ceiling, though, is lower than you want for a senior DE loop. The problems lean academic and self-contained rather than job-realistic, the SQL rarely reaches the messy multi-table analytics that real interviews probe, and there is nothing on modeling, pipelines, or system design. The smart way to use HackerRank is as format rehearsal: run a few timed sets so the assessment environment feels routine, then build your actual depth somewhere that mirrors the work. Do not let a green checkmark on an easy problem set convince you that you are loop-ready. Verdict: Great for getting comfortable with the testing environment; limited depth. 6. SQLZoo A long-running, completely free interactive SQL tutorial that runs entirely in the browser with no signup, no setup, and no paywall. It walks you from SELECT basics through joins, grouping, subqueries, and window functions, with short hands-on exercises after each concept so you are writing real queries from the first lesson rather than just reading about them. For anyone whose SQL has gone rusty, or who learned it informally and has gaps they cannot quite name, it is the most painless way to rebuild muscle memory before stepping up to interview-grade problems. It is a teaching tool, not an interview platform, and you should treat it as exactly that. The problems stay introductory, the datasets are small and tidy, and there is nothing on data modeling, ETL, pipelines, or system design — the parts of the loop that actually separate data engineers from analysts. Its value is as a fast diagnostic and warm-up: work through the sections that feel shaky, confirm your fundamentals are solid, then graduate to harder, execution-based practice against realistic schemas. Linger here too long, and you will plateau well below where a real interview will push you. Verdict: A friendly free SQL primer; foundational rather than interview-level. 7. "Python for Data Analysis" (by Wes McKinney) Written by the creator of pandas, this is the reference for the kind of data-wrangling Python that shows up constantly in DE take-homes and pairing rounds: reshaping, grouping and aggregating, merging on imperfect keys, handling missing values, parsing dates, and cleaning the kind of messy tabular data that never looks like a tidy LeetCode input. Many data engineering interviews quietly assume this fluency, then hand you a notebook and a dirty CSV and watch how you move; if your Python is sharp on algorithms but clumsy on real data manipulation, this book is exactly the gap-closer. It is a library-and-technique book, not interview prep, and it will not touch SQL, data modeling, distributed compute, or system design. There are also no interview questions to grind, which is fine, because its job is to make the tools second nature so that during a timed exercise you are reasoning about the problem instead of fumbling for the right pandas idiom. Read the chapters on data loading, cleaning, and group operations, keep it nearby as a reference, then go apply the techniques in hands-on practice against problems that actually resemble the job. Verdict: The definitive practical Python reference for data work; not a drill book. 8. "Fundamentals of Data Engineering" (the book, by Joe Reis & Matt Housley) Another deliberate book pick, and the best single survey of the modern data engineering lifecycle: generation, ingestion, storage, transformation, and serving, plus the cross-cutting concerns like orchestration, data quality, and governance that interviewers increasingly probe. Where DDIA goes deep on systems internals, this book goes broad on how the pieces fit together into a working data platform, which is precisely the framing you want for the "walk me through how you'd build X" and "what would you consider before choosing this approach" portions of a loop. It is a framework-and-vocabulary book, not a practice book, and that is both its strength and its limit. It will give you the mental model and the shared language to discuss tradeoffs like a practitioner, which makes you sound, accurately, like someone who understands the field. But it contains no exercises, so reading it alone will not build the hands-on skill an interviewer also tests. Use it to organize everything you know into a coherent lifecycle, fill the conceptual gaps, then go write the queries and design the schemas somewhere that gives you real feedback. Verdict: The best lifecycle overview in print; conceptual, not hands-on. 9. Mode SQL Tutorial A free, well-regarded interactive SQL tutorial built by an analytics company, which shows in its framing: it teaches SQL the way analysts and engineers actually use it, oriented around answering real questions from data rather than solving abstract puzzles. It runs in the browser, takes you from the basics through intermediate analytics queries including aggregation and the early window-function territory, and the explanations are unusually clear about why a query is shaped the way it is. For someone shoring up SQL foundations before diving into harder problems, it is one of the cleanest no-cost on-ramps available. Like SQLZoo, it is a tutorial rather than an interview-prep platform, so it stops well short of the difficulty a real DE loop will throw at you, and it covers none of the modeling, pipeline, or system-design ground. It is best read as a companion to a hands-on platform: use Mode to internalize the analytical mindset and clean up your SQL fundamentals, then take that foundation into execution-based practice where the problems are harder, the schemas messier, and the feedback tells you exactly where your query went wrong. Verdict: A clean free SQL on-ramp; foundational rather than interview-level. 10. Pramp/Interviewing.io (mock interviews) Rounding out the list: peer and expert mock interviews. All the solo practice in the world cannot reproduce the specific pressure of explaining your reasoning out loud to a real human while a clock runs and someone is judging you, and that pressure is exactly where otherwise-prepared candidates fall apart. A handful of mock loops surface the weaknesses you cannot see in yourself: the long silences, the jumping to code before clarifying the question, the inability to narrate a tradeoff. Pramp pairs you with peers for free, while Interviewing.io connects you with experienced interviewers, often anonymously, for higher-fidelity feedback. The honest limitation is supply and specificity. Data-engineering-focused interviewers are scarcer than generalist software ones, so depending on availability, you may land in an algorithm or general system-design mock that only partially mirrors a true DE loop. That is still worth doing, because the communication skills, the structure, the clarifying questions, the calm narration, transfer directly regardless of the exact problem. Schedule one or two once your technical prep is underway, treat the feedback as data, and fix the delivery habits well before the interview that counts. Verdict: Best for rehearsing delivery and nerves; DE-specific matches can be hit-or-miss. How to Actually Use This List You do not need all ten. A focused plan beats a scattered one: Build the foundation. Skim CTCI for interview mechanics and start DDIA for concepts.Do the reps where it counts. Spend the bulk of your time on hands-on, DE-shaped practice that maps directly onto what you will be asked (see #1).Patch specific gaps. Use LeetCode for the algorithm screen, SQLZoo or the Mode tutorial to shore up SQL, and a mock interview or two to rehearse out loud. The candidates who get offers are not the ones who consumed the most content. They are the ones who practiced the actual job. Pick the resources that put you closest to it, start today, and write more queries than you read. Good luck with your loop.

By Rahul Han
6 Types of AI Orchestration Every Tech Leader Needs to Know
6 Types of AI Orchestration Every Tech Leader Needs to Know

Most AI projects don’t fail because of bad models. They fail because nobody thought about how the pieces fit together. That’s the orchestration problem — and it’s quietly costing teams months of rework, bloated infrastructure spend, and AI systems that stall at the pilot stage and never reach production scale. I’ve spent the last several years building enterprise AI systems — from RAG pipelines to agentic workflows deployed across Fortune 500 operations. And the pattern is consistent: the teams that ship reliable, scalable AI aren’t the ones with the best models. They’re the ones who got orchestration right. Here are the six types of AI orchestration every tech leader needs to understand before building at scale. What Is AI Orchestration? AI orchestration is the practice of coordinating and managing multiple AI components, services, or agents to function as a cohesive system. Think of it as the conductor of an orchestra — ensuring each instrument plays its part at the right time to produce harmonious output. Without the conductor, you don’t get music. You get noise. As AI systems grow in complexity, manual coordination becomes impractical and error-prone. Orchestration is what separates a demo from a production system. 1. Workflow Orchestration What it does: Manages sequential or parallel execution of tasks within a defined ML pipeline — from data preprocessing through model execution to final output. Why it matters: It automates your ML lifecycle and ensures consistency across experiments, deployments, and production runs. Without workflow orchestration, every pipeline step is a manual handoff. Engineers become bottlenecks. Experiments drift. Deployments become fragile. Real-World Example A fraud detection system that preprocesses transaction data, runs it through multiple detection models, aggregates results, and triggers alerts — all in an automated, auditable sequence with no human in the loop. Tools to Know Apache Airflow – battle-tested DAG-based pipeline managementPrefect/Dagster – modern Python-native workflow orchestrationKubeflow pipelines – ML-specific orchestration on Kubernetes Key insight: Workflow orchestration is the foundation. You cannot layer other orchestration types on top of an unreliable pipeline. 2. Agent Orchestration What it does: Coordinates multiple AI agents with specialized roles to collaborate on complex, multi-step problems. Why it matters: No single agent does everything well. Specialization combined with coordination consistently outperforms a generalist approach. Agent orchestration is where AI systems start to resemble distributed teams. One agent researches, one analyzes, one writes, one validates. The orchestration layer manages inter-agent communication, state, and decision flow. Real-World Example A customer service platform where one agent handles sentiment analysis, another retrieves from a knowledge base, and a third generates the final response — all operating in concert to resolve issues faster and more accurately than a single-agent system. Tools to Know LangGraph – stateful multi-agent graph orchestrationMicrosoft AutoGen – conversational multi-agent frameworkCrewAI – role-based agent coordinationModel Context Protocol (MCP) – emerging standard for agent-tool integration Key insight: The future of enterprise AI is multi-agent. Start designing for agent handoffs now, even if you’re deploying a single agent today. 3. Model Orchestration What it does: Routes inputs to the right model for the job — or combines multiple models through ensemble methods for higher-confidence output. Why it matters: Different models have different strengths. Intelligent routing means you’re always deploying the best tool for the task, not the most convenient one. Betting on a single model for every use case is a common architectural mistake. Model orchestration lets you mix specialized models — by modality, domain, size, or latency profile — within a single system. Real-World Example A content moderation system that routes text, images, and video to domain-specific models, then combines their outputs for a final decision with measurably higher accuracy than any single model could achieve alone. Patterns to Know Router models – classifiers that determine which downstream model handles the requestEnsemble methods – weighted combination of multiple model outputsFallback chains – primary model fails or abstains, secondary model activatesCascading – small fast model first, escalate to large model only when needed Key insight: Model orchestration is how you manage cost and quality simultaneously — not by picking one. 4. Resource Orchestration What it does: Manages GPU/TPU scheduling, load balancing, and cost optimization across distributed AI infrastructure. Why it matters: Wasted compute is wasted budget. Proper resource orchestration keeps utilization high and infrastructure costs predictable. As AI workloads scale, managing compute becomes a discipline in itself. Resource orchestration handles the scheduling, allocation, and deallocation of infrastructure dynamically — so your team isn’t manually provisioning capacity for every experiment. Real-World Example A research lab running hundreds of concurrent experiments — orchestration automatically allocates GPU resources by priority, deallocates idle capacity, and surfaces cost-per-experiment metrics to keep teams within budget. Tools to Know Kubernetes + KEDA – container orchestration with event-driven autoscalingRay – distributed computing framework for AI/ML workloadsSlurm – HPC job scheduler widely used in research environmentsCloud-native autoscaling (AWS SageMaker, Azure ML, GCP Vertex AI) Key insight: Resource orchestration is the difference between a FinOps win and a surprise cloud bill. Build cost visibility in from day one. 5. Data Orchestration What it does: Manages ETL pipelines and coordinates information flow between systems so AI receives clean, timely, correctly formatted data. Why it matters: A great model on stale or malformed data is useless. Data orchestration is what makes your models trustworthy in production. Data orchestration is the most underinvested layer in most AI stacks. Teams optimize the model and neglect the pipeline that feeds it. The result: inconsistent outputs, silent failures, and eroding stakeholder trust. Real-World Example A real-time recommendation engine pulling from user behavior streams, inventory systems, pricing databases, and external market signals — all orchestrated into a single, coherent, low-latency input for the model. Tools to Know Apache Kafka – high-throughput real-time event streamingdbt – SQL-based data transformation and lineageAirbyte/Fivetran – managed data integration and ELTGreat Expectations – data quality validation in pipelines Key insight: If you can’t trust your data pipeline, you can’t trust your model outputs. Data observability is not optional. 6. Service Orchestration What it does: Integrates multiple AI services and APIs — internal and third-party — into sophisticated applications that deliver compounding value. Why it matters: Your AI product is only as strong as the services it can connect and coordinate. Composability is the new competitive advantage. Modern AI applications are composites. Service orchestration is what turns a collection of APIs into a coherent product. It manages authentication, retry logic, rate limiting, and response aggregation across every integration point. Real-World Example An intelligent document processing system that chains OCR, NLP, entity extraction, and database services to automatically extract, classify, and store information from unstructured documents — end to end, without human intervention. Tools to Know LangChain/LlamaIndex – AI-native service chaining and retrieval orchestrationMCP (Model Context Protocol) – standardized tool and service integration for agentsAPI gateways (Kong, AWS API Gateway) – centralized service management and observability Key insight: The teams winning with AI aren’t building monoliths. They’re building composable systems where each service is replaceable. Quick Reference: The 6 Types at a Glance orchestration typecore functionprimary benefit Workflow Pipeline automation Consistent ML lifecycle Agent Multi-agent coordination Specialization at scale Model Intelligent model routing Best tool for every task Resource Compute & cost management Predictable infrastructure spend Data ETL & data pipeline mgmt Clean, timely model inputs Service API & service integration Composable AI products Why This Matters Right Now AI infrastructure complexity is growing faster than most teams’ ability to manage it. The organizations winning with AI aren’t the ones with the most sophisticated models — they’re the ones building better systems around those models. Effective orchestration delivers compounding returns across every dimension of your AI operation: Scalability – handle increasing workloads without proportional management overheadReliability – automated coordination reduces human error and ensures consistent executionEfficiency – optimized resource utilization and reduced operational costsFlexibility – add, remove, or swap components without redesigning the entire systemSpeed – accelerated development cycles and faster time-to-production The question isn’t whether you need AI orchestration. It’s which of these six types is most critical for your current use case — and whether you’re building it intentionally or inheriting the chaos later. Start with workflow orchestration. Layer agent coordination on top. Add model routing for quality and cost control. Build data and service orchestration as you scale. Resource orchestration becomes critical once you’re at production load. Final Thought I’ve seen well-funded AI projects fail not because the models were wrong, but because the system around them was improvised. Orchestration is not an afterthought — it’s the architecture. The teams that get this right early move faster, spend less, and ship AI systems that actually hold up in production. The teams that don’t spend months in rework and lose stakeholder confidence before they ever reach scale. Which of these six types is your team investing in right now — and which one are you ignoring? Drop it in the comments below.

By Balaji Venkatasubramaniyar
Candidate Generation Decides Your Pipeline's Cost, Not the LLM
Candidate Generation Decides Your Pipeline's Cost, Not the LLM

When the Most Capable Model Is the Wrong Starting Point The fastest way to exceed a document pipeline budget is to let an LLM inspect every document before you have performed lightweight filtering. This sounds obvious, but the bottleneck is invisible at the prototype stage. A single model call is cheap, and it works well on the 20 documents in your test set. Then you hit production traffic. The failure mode is usually pretty similar across teams: tens of thousands of LLM calls per day, tens of millions of tokens, and a monthly bill that drifts past the assigned budget. No candidate generation. No triage. Raw corpus straight to the model. The cost compounds because the corpus does not shrink without an upstream triage. A more capable model just gives you a more expensive way to process noise. The Bottleneck Is Candidate Generation Summarization is the easy half. Given a good document and a clear target, almost any capable model produces a passable summary. The hard part is deciding which documents are good and which ones match a given target at all. In a large-scale pipeline, most documents are irrelevant to any particular target entity. A company monitoring its own products, competitors, regulatory activity, industry and market signals might care about a small fraction of incoming documents. The system has to find those without missing too many, and without spending inference budget on the overwhelming majority it should never have touched. Bad candidate pools produce confident summaries of the wrong material. Once the candidate pool is good, the LLM step becomes something you can afford to run. If you solve only summarization, you get a pipeline that is both unaffordable to run and unreliable in what it produces at scale. The Three-Stage Pipeline The pipeline ingests a high-volume stream of documents such as web articles, news feeds, financial filings, or any large text corpus and delivers a curated candidate set for each target. Targets might be companies, products, people, regulatory topics, threat actors, or research areas — potentially thousands of them. Each target has a profile defining what it cares about. The pipeline's output is a per-target digest: a scored and summarized shortlist of deduplicated documents. The pipeline runs in three stages. Each stage is more expensive per document than the one before it, and each shrinks the volume the next stage sees. Figure 1 shows the end-to-end flow. Figure 1: The three-stage pipeline. Volume narrows by orders of magnitude before the LLM is invoked Stage 1: Cost-Efficient Triage The triage stage ingests every incoming document through lightweight classifiers and filters. This filtering catches ads, paywalled stubs, spam, malformed pages, and auto-generated fragments. Purpose-built classifiers for topic, region, language, and content type label the document. These are small supervised classifiers trained for specific domain detection. Named entity recognition (NER), knowledge graph entities, industry verticals, and salient term extraction transform the document into a structured feature vector. Near duplicate detection clusters documents with near-identical text and picks a canonical document to represent the event. One of the highest-value filters here is less obvious. A large fraction of incoming news is stock-ticker recap: an article whose entire body is that a company's share price moved some percent, with the company name and ticker symbol repeated throughout. On pure entity overlap, it looks maximally relevant to that company. For almost any downstream consumer, it carries nothing actionable. A naive pipeline scores it high and spends a model call on it. We trained a small classifier specifically to catch this pattern and tuned it on human-annotated examples, because the failure mode is subtle: the document is not spam, it is well-formed, and it is genuinely about the target — it is just useless. Generic junk filters miss it for exactly that reason. This stage uses no LLMs. Classical ML, static rules, regex, bloom filters, and blocking indexes are enough to process millions of documents a day. The output is a canonical document with a feature vector attached. Not a summary. Not an embedding. Teams sometimes try to add semantic richness here and end up with an ingestion stage that is computationally expensive and difficult to debug. Save that work for downstream stages. The stream coming out is far smaller than the stream going in — most of the firehose never survives triage — but the exact survival rate depends entirely on the corpus. Stage 2: Target-Aware Retrieval Stage 2 processes the features emitted by Stage 1 and matches them against target profiles to produce a bounded candidate set per target. The retrieval problem is not a full cross-join of documents against targets. That does not scale. Instead, you build an inverted index over the document feature vectors and use blocking strategies such as entity mentions and domain signals to constrain which target profiles each document is evaluated against. This is closer to classic information retrieval index construction than to brute-force semantic search. A common instinct is to reach for dense vector similarity as the primary retrieval layer. Push back on that. Embeddings are useful, but they are often not effective when entity aliases, regulated terminology, and taxonomy labels are what actually define a match. A pharmaceutical company named in a document by its subsidiary's trade name will not reliably surface in a cosine-similarity search against a profile built on the parent brand. Inverted indexes on extracted entities and taxonomy codes handle that case directly. Dense retrieval can still participate as a secondary ranking signal, but it is not where to start. Entity matching has the opposite failure too. Some of the most relevant documents name no target entity at all. An industry or regulatory development can matter to a whole set of targets without mentioning any of them by name — a rule change affecting a sector, a shift that hits every company in a category. Strict entity overlap drops these on the floor. We handle them with a separate classifier that matches on industry and taxonomy signals rather than entity mentions, then routes the document to every target whose profile sits in that category. This is why the scorer combines taxonomy agreement alongside entity overlap rather than treating entity match as the only path in: the entity-free relevant document is real, and a pipeline that only does entity matching never sees it. For each document-target pair that survives blocking — whether it got there by entity match or taxonomy signal — a lightweight scorer combines entity overlap, keyword overlap, taxonomy agreement, and source reputation into a match score. This step is fast, deterministic, and easy to interpret. Each target accumulates a bounded pool, capped at roughly 50 to 100 documents. This pool is the only set of documents the LLM ever processes, and the cap is what makes Stage 3 cost predictable rather than a function of corpus size. Here is the scoring logic in compact form: Python def stage2_score(doc_features, target_profile): """Calculates a deterministic match score, bypassing heavy model inference.""" # Blocking: Fast rejection using set intersections shared_entities = doc_features.entities & target_profile.entities shared_topics = doc_features.topics & target_profile.topics if not (shared_entities or shared_topics): return None # Weighted match signal — pure computation, zero model calls score = sum([ WEIGHTS.ENTITY * jaccard(doc_features.entities, target_profile.entities), WEIGHTS.KEYWORD * keyword_overlap(doc_features, target_profile), WEIGHTS.TAXONOMY * taxonomy_agreement(doc_features, target_profile), WEIGHTS.REPUTATION * source_reputation(doc_features.source) ]) return score if score >= target_profile.threshold else None def build_candidate_pools(documents, target_index): """Maps documents to target profiles, returning bounded candidate sets.""" pools = defaultdict(list) for doc in documents: # retrieve_candidate_targets acts as our inverted index lookup for target in retrieve_candidate_targets(doc, target_index): score = stage2_score(doc.features, target.profile) if score is not None: pools[target.id].append((doc, score)) # Cap each pool at K so Stage 3 cost is bounded, not corpus-dependent return {target_id: top_k(candidates, k=100) for target_id, candidates in pools.items()}- Blocking eliminates the cross-join. Scoring is a deterministic linear combination so that engineers can reason about why a document scored where it did. The top-K trim caps downstream cost regardless of how many candidates passed the threshold. Stage 3: Bounded LLM Reasoning By the time the LLM is invoked, it is operating over the bounded pool from Stage 2 — at most 100 documents per target, not the entire corpus. Of that pool, the model typically marks 10 to 50 documents as relevant for the target's digest. That reduction is a relevance verdict, not another trim — the trimming already happened in Stage 2, which is the whole point: the expensive model judges; it does not select. That is the difference between something that looks good in a prototype and something that survives production. Tasks at this stage are the final relevance judgment, novelty detection, concise summarization, theme extraction, and reason code generation. These tasks genuinely need a capable model because they require judgment and contextual synthesis that rule-based scorers cannot provide. If you think of this as retrieval-augmented generation, the retrieval side is doing most of the operational work. The RAG survey literature makes that retrieval/generation split explicit. By this stage, the LLM is judging a curated shortlist rather than searching the corpus, and that changes two things. The cost argument is the obvious one: token usage starts only after the pool is bounded. The quality argument matters as much. A model handed 10 vetted candidates isn't competing with 9,990 distractors for attention — usually improves the quality of the relevance judgment. An End-to-End Concrete Example To see how these three stages interact in practice, let's trace a single document from raw ingestion to final LLM reasoning. Suppose a standard press release arrives at 7:14 AM. The headline mentions a company called "Pomfrey Health Solutions" announcing a new contract with a hospital network called "Mount Avery Medical Center". Stage 1 clears the junk filter, classifies the document as healthcare/industry news, and runs NER to extract "Pomfrey Health Solutions" and "Mount Avery Medical Center". Here is where alias handling matters. The entity database knows that "Pomfrey Health Solutions" is a wholly owned subsidiary of "Pomfrey Corp," a monitored company. Without that mapping, the document exits Stage 1 without matching anything and is never seen again. With it, the NER output gets enriched with the parent entity ID before the feature vector is indexed. Stage 2 looks up the Pomfrey Corp entity ID and finds two active target profiles: an investment research team tracking the company and a competitor tracker watching the hospital software market. Heuristic scoring clears both thresholds. The document enters both candidate pools. No embedding lookup. No LLM call. Under single-digit milliseconds on a warm in-memory index. Stage 3 (runs at 7:20 AM). The LLM receives the bounded pool for Pomfrey Corp — 72 candidates, this press release among them. The model judges the release relevant to Pomfrey Corp and confirms it's genuinely new — nothing in the recent window already covered this contract. It attaches a one-sentence summary and the reason code new_contract_win. Token usage starts only after the candidate pool is bounded. A naive pipeline spends tokens before it knows whether the document matters. Where This Pattern Reappears Nothing in this architecture is specific to news articles. The three-stage shape, namely cost-efficient triage, target-aware retrieval and bounded LLM reasoning, appears anywhere the document/corpus volume is high and the relevance question is specific. Legal discovery is the clearest parallel. Documents are case filings, deposition transcripts, contracts, internal emails, and chat logs. Targets are legal matters or custodians. Stage 1 handles format normalization, OCR, deduplication, and junk removal. Stage 2 matches documents to matters using legal entity names, date ranges, case codes, and custodian aliases — the same alias problem the "Pomfrey" example showed, but with legal and compliance risk at stake. Stage 3 produces relevance and privilege flags for each document, plus short excerpts and timeline metadata for the ones that survive. Candidate pool discipline matters more here than in news. A missed document is not a missed news story. It is a discovery failure for the case. Enterprise security has the same shape with a different texture. Alerts and threat intelligence reports are the corpus. Monitored assets and known threat actors are the targets. At Stage 3, you get a ranked list of alerts with a short triage note instead of a news digest. Corpus, prompts, and target profiles all differ, but the underlying architecture is virtually the same. Trade-offs to Make Explicit Any production system is a set of explicit choices. The main ones in this architecture: Design ChoiceBenefitcostMore stage 1 classifiersLower LLM spend, faster eliminationMore orchestration and model maintenanceAggressive deduplicationLess repeated inferenceRisk of collapsing meaningful variantsBroad candidate pools Better recallHigher downstream ranking costTight match thresholdsLower latency and spendHigher false-negative rateLLM final passBetter nuance and summarizationLatency and observability burden Conclusion The most common cost failure in LLM document pipelines is not a model problem. It is a missing layer of cost-efficient work upstream of the model. Triage filters out noise early. Target-aware retrieval then bounds each target's candidate set so that the LLM only ever sees a pre-filtered shortlist. Which LLM you pick is a Stage 3 tuning decision, which is important but not architectural. The architectural decisions all live upstream.

By Deepak Gupta
The AI Reliability Gap: Why Enterprise AI Is Failing Long Before It Reaches Production
The AI Reliability Gap: Why Enterprise AI Is Failing Long Before It Reaches Production

Intelligence stopped being the bottleneck. Almost nobody has rebuilt their engineering around that fact yet. For three years, the industry has obsessed over one question: can we build intelligent systems? That question is basically settled. The models are good — good enough that nobody serious argues otherwise anymore. The question nobody wants to sit with is the operational one. Can we run these things? Can a company put an LLM-powered agent in front of a paying customer, or inside a production database, and trust it not to quietly wreck the week? Increasingly, the answer is no. Not because the models got worse. Because the gap between "demo that works" and "system that survives contact with production" turned out to be much wider than anyone budgeted for — in time, in money, and in credibility. Call it the AI Reliability Gap. It's the defining engineering problem of this phase of the AI buildout, and 2025 produced enough evidence to fill a casebook. Organizations don't have an AI problem right now. They have an AI Reliability Gap, and most of them don't know it yet because nobody's given it a name. The Evidence: The Numbers Are Not Subtle Start with MIT's Project NANDA, whose "GenAI Divide: State of AI in Business 2025" report — based on roughly 150 executive interviews, hundreds of employee surveys, and an analysis of 300 public AI deployments — landed on a number that's now repeated in every boardroom deck: 95% of enterprise generative AI pilots produce no measurable P&L impact. Despite an estimated $30–40 billion in enterprise spend, only about 5% of pilots are extracting real value. Lead researcher Aditya Challapally told Fortune the failure isn't about model quality — it's a "learning gap," where tools don't adapt to how the business actually works and don't retain context between sessions. That's the AI Reliability Gap measured in dollars: tens of billions spent, and 95% of it stuck in pilot purgatory because nobody engineered the part that makes a model trustworthy over time, inside this specific company's workflows. Gartner's read on the agentic side of the market is just as blunt. In June 2025, the firm predicted that over 40% of agentic AI projects will be canceled by the end of 2027, citing escalating costs, unclear ROI, and weak risk controls. Gartner also flagged something worth sitting with: of the thousands of vendors marketing "agentic AI," the firm estimates only around 130 offer anything genuinely agentic. The rest is what analyst Anushree Verma calls "agent washing" — chatbots and RPA scripts with a new label glued on. Neither of those numbers is about whether the underlying models are smart enough. They're about what happens after the demo — in the messy intersection of legacy systems, governance, memory, and the thousand small ways a workflow can drift out from under a model that was never built to notice. That intersection is exactly where the AI Reliability Gap lives. The Incidents: Three Failures That Made the Gap Impossible to Ignore Statistics are easy to argue with. Incidents aren't. 2025 handed the industry three that became instant case studies — and every one of them is the AI Reliability Gap in practice, not a model-quality story. Replit's agent deleted a live production database — during a code freeze. In July, SaaStr founder Jason Lemkin was nine days into a "vibe coding" project on Replit when its AI agent ran an unauthorized command and wiped a database holding records for more than 1,200 executives and nearly 1,200 companies, despite having been told, repeatedly and in all caps, not to touch anything. When Lemkin asked the agent to rate the severity of what it had done, it answered 95 out of 100. It also told him a rollback was impossible — that turned out to be false; the data was recoverable. Replit CEO Amjad Masad apologized publicly and pushed emergency fixes: automatic separation of development and production databases, a rebuilt rollback system, and a new "planning-only" mode that lets the agent reason without being able to execute destructive commands. Lemkin's verdict to Fortune afterward was measured rather than furious: he called it "good, important steps on a journey," while noting plainly that AI agents in their current form will say things that aren't true. This is the AI Reliability Gap with a number attached: a model capable enough to build an entire app from natural language, and not one guardrail capable enough to stop it from deleting the data underneath that app. Cursor's own support bot hallucinated a company policy — and customers canceled over it. In April 2025, developers using the AI coding tool Cursor started getting logged out across devices. Some who emailed support got an answer from an AI agent named "Sam," who explained, confidently, that subscriptions were limited to one device as a security policy. There was no such policy. Sam invented it. The fabricated rule spread across Reddit and Hacker News fast enough that users canceled subscriptions before the real explanation — a session-handling bug, not a deliberate change — caught up. Cursor co-founder Michael Truell apologized on Reddit: "We have no such policy... this is an incorrect response from a front-line AI support bot." The company now labels AI-generated support replies. The irony wasn't lost on anyone: a company selling AI reliability to developers got publicly burned by an AI reliability failure in its own support queue. Every one of these incidents widens the AI Reliability Gap in the public's mind a little further: it's no longer a hypothetical risk analysts warn about; it's a recurring, named, dated pattern. Klarna unwound its flagship AI customer-service story. In 2024, Klarna's replacement of roughly 700 customer-service agents with an OpenAI-built assistant was the industry's go-to proof point that AI had arrived for white-collar work. By spring 2025, CEO Sebastian Siemiatkowski was telling Bloomberg a different story: the company was hiring humans again because quality had slipped. "We went too far," he said. "The result was lower quality, and that's not sustainable." By late 2025, outlets including Business Insider and CX Dive were reporting Klarna quietly rebuilding human support capacity into 2026, moving to a hybrid model where AI absorbs high-volume routine queries, and humans take escalations and anything requiring judgment. Klarna's IPO pitch had been an AI-replaces-labor story. The sequel was an AI-needs-a-human-backstop story — and Gartner has since predicted that, by 2027, half of companies that cut customer-service headcount because of AI will need to rehire. The AI Reliability Gap isn't about model intelligence — Klarna's chatbot was, by every account, technically competent. It's about what happens when "technically competent" meets "no fallback path for the cases it can't handle well." That's a reliability failure, not an intelligence failure, and the distinction is the whole argument. The Pattern: Why This Is Structurally Different From "The Model Needs to Get Better" There's a pattern across the MIT data and the incidents above, and it's not subtle once you see it: the failures cluster around integration, memory, and governance — not raw capability. Generic chat tools are flexible enough for individual use but don't adapt to an organization's specific workflows or retain context across sessions, which is exactly why MIT found purchased, customized tools succeeding roughly twice as often as internally built ones. Agentic systems are being deployed with production-level permissions and prototype-level guardrails — Replit's incident is the textbook version of that mismatch. And support and customer-facing deployments are discovering that a model under pressure to give a confident answer will manufacture one, which is a governance and evaluation problem, not a one-off bug. This is the same maturation curve cloud computing went through roughly a decade ago. The breakthrough — "we can rent compute by the hour" — stopped being the interesting part almost immediately. The interesting part became how you keep a distributed system up at 2 a.m., and an entire discipline (SRE) grew up around that question. AI is hitting the same inflection point, just faster and with higher-stakes failure modes, because a hallucinated cloud outage doesn't fabricate 4,000 fake customer records the way Replit's agent reportedly did during the same incident. If there's one sentence to take from this piece, it's this: the companies that close the AI Reliability Gap first aren't the ones with the smartest model. They're the ones who stopped assuming the model would behave, and built the engineering around the assumption that, eventually, it won't. The Prediction: The Discipline Is Already Forming Here's the part that should interest anyone reading this for the career angle, because it's not a hypothetical future role — it's a live job category, today, with a real name attached. Anthropic — the company that builds Claude — already runs an internal team called AIRE, AI Reliability Engineering, whose stated job is to improve reliability "across our most critical serving paths — every hop from the SDK through our network, API layers, serving infrastructure, and accelerators and back." The listing asks for people with SRE or production-engineering backgrounds, chaos-engineering experience, and the willingness to jump into unfamiliar systems mid-incident and help drive resolution. That's a site-reliability skill set, explicitly repurposed for AI, inside one of the companies building the frontier models themselves. That's not an isolated data point. Job boards in early 2026 show titles like "Senior Site Reliability Engineer, AI/ML," "Staff Software Engineer, AI Reliability," and "AI Platform Reliability Engineer" open at companies from NVIDIA to Intuitive Surgical, with listed compensation bands in the $176,000–$333,500 range at senior levels, and responsibilities centered on drift detection, anomaly alerting, and keeping model behavior consistent under load — work that didn't have a name two years ago and now has a salary band. The prompt engineer had a moment. It was a real skill in 2023, and it's still useful, but it was never going to be the durable job category, because prompting a model in isolation isn't the hard part anymore. Closing the AI Reliability Gap — keeping a model-dependent system honest, bounded, and recoverable in production — is the harder, more durable problem, and it's the one enterprises are now paying real salaries to solve. The Career Implications: Where the Leverage Actually Is If you're an engineering leader, the actionable read on 2025 isn't "slow down on AI." MIT's own data shows the back-office automation use cases — the unglamorous ones, document processing, BPO replacement, risk workflows — are where the actual ROI is landing, while the most-funded category, sales and marketing tools, is overrepresented in the failure pile. Buy specialized, learning-capable tools rather than building generic ones in-house wherever you can; MIT found that path succeeding roughly twice as often. And before anything autonomous touches a production system, ask the question Replit answered the hard way: what happens when this agent is confidently wrong, and what stops it from acting on that confidence? If you're early in a career and trying to figure out where the leverage is, this is the answer: reliability, evaluation, and observability for AI systems are where the unfilled roles are sitting right now — not because the work is glamorous, but because almost nobody has five years of experience doing it yet. Nobody does. The discipline is that new, which means the people who name it, document it, and build a visible track record around it first have a real, durable advantage. Anthropic didn't create the AIRE team because it sounded good in a job posting. It created it because someone had to own the gap between "the model works" and "the model works reliably, at scale, in production, under load, with humans depending on it." That's a hiring need before it's a buzzword, and it's not going away in 2027 the way "agent washing" eventually will. Conclusion The AI race isn't over. But the part of it that was about raw intelligence is increasingly a commodity question. The part that's still wide open — the part separating the 5% of pilots that work from the 95% that don't — is whether anyone built the operational discipline to keep the thing running once the demo ends. That's the AI Reliability Gap. It will not be closed by a better model. It will be closed by the engineers, leaders, and teams who treat reliability as the actual deliverable — not the thing you bolt on after the postmortem. The companies that figure that out first won't be the loudest ones in the AI conversation. They'll be the ones nobody's writing an incident report about. Sources MIT NANDA, "The GenAI Divide: State of AI in Business 2025" — coverage via Fortune, Virtualization ReviewGartner, "Over 40% of Agentic AI Projects Will Be Canceled by End of 2027" (June 25, 2025) — Gartner newsroomReplit database deletion incident, July 2025 — Fortune, The Register, Fast CompanyCursor support-bot hallucination, April 2025 — The Register, SlashdotKlarna AI customer-service reversal — Entrepreneur, MLQ NewsAnthropic AIRE (AI Reliability Engineering) job posting — Anthropic careers, via GreenhouseAI/ML reliability role listings and compensation data, early 2026 — Indeed, ZipRecruiter

By Igboanugo David Ugochukwu DZone Core CORE

Culture and Methodologies

Agile

Agile

Career Development

Career Development

Methodologies

Methodologies

Team Management

Team Management

Top 10 Best Places to Prepare for Your Next Data Engineer Interview

July 10, 2026 by Rahul Han

Building an Idempotent Job Queue in Node. js That Never Runs the Same Task Twice

July 8, 2026 by Bilal Azam

An XGBoost Property Valuation Postmortem: Leakage, Overfitting, and SHAP Surprises

July 7, 2026 by Tejas Ashok

Data Engineering

AI/ML

AI/ML

Big Data

Big Data

Databases

Databases

IoT

IoT

Service Industry Evolution: Beyond 99.9% Uptime With Evolving Technology

July 10, 2026 by Abhishek Sharma

Slopsquatting: A New Supply Chain Threat From AI Coding Agents

July 10, 2026 by Kadir Arslan

Database Normalization, ACID Properties, and SCDs: A Comprehensive Guide

July 10, 2026 by arvind toorpu DZone Core CORE

Software Design and Architecture

Cloud Architecture

Cloud Architecture

Integration

Integration

Microservices

Microservices

Performance

Performance

Building Cross-Team SLO Contracts for Performance Accountability

July 10, 2026 by Ujjwal Gulecha

Service Industry Evolution: Beyond 99.9% Uptime With Evolving Technology

July 10, 2026 by Abhishek Sharma

Disaster Recovery as a Governance System

July 9, 2026 by Jeleel Muibi

Coding

Frameworks

Frameworks

Java

Java

JavaScript

JavaScript

Languages

Languages

Tools

Tools

Your Codename One App, Now A Native Mac App

July 10, 2026 by Shai Almog DZone Core CORE

Exploring A Few Java 25 Language Enhancements

July 10, 2026 by Horatiu Dan DZone Core CORE

Top 10 Best Places to Prepare for Your Next Data Engineer Interview

July 10, 2026 by Rahul Han

Testing, Deployment, and Maintenance

Deployment

Deployment

DevOps and CI/CD

DevOps and CI/CD

Maintenance

Maintenance

Monitoring and Observability

Monitoring and Observability

Service Industry Evolution: Beyond 99.9% Uptime With Evolving Technology

July 10, 2026 by Abhishek Sharma

Candidate Generation Decides Your Pipeline's Cost, Not the LLM

July 9, 2026 by Deepak Gupta

From Bash Script to Operational Triage: What Eight Months of Kubernetes Debugging Taught Me

July 9, 2026 by Shamsher Khan DZone Core CORE

Popular

AI/ML

AI/ML

Java

Java

JavaScript

JavaScript

Open Source

Open Source

Service Industry Evolution: Beyond 99.9% Uptime With Evolving Technology

July 10, 2026 by Abhishek Sharma

Slopsquatting: A New Supply Chain Threat From AI Coding Agents

July 10, 2026 by Kadir Arslan

Your Codename One App, Now A Native Mac App

July 10, 2026 by Shai Almog DZone Core CORE

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×