Recommended resources
The freely available resources this lesson will direct you to.
- Caching Pitfalls Every Developer Should Knowwww.youtube.com
- The definitive guide to Java agents by Rafael Winterhalterwww.youtube.com
- [PDF] Adaptive Filtering and Sampling in Runtime Software Monitoringlume.ufrgs.br
- [PDF] Understanding and Selecting Runtime Application Self- Protectioncdn.securosis.com
Hello! Welcome to the next lesson in our course on architecting security products.
In our last lesson, we designed the "brain" of our RASP—a sophisticated vulnerability detection engine using Abstract Syntax Trees (ASTs) to analyze runtime context and spot attacks like SQL and command injection. We now have a powerful analysis capability, but this power comes at a cost: performance. Every nanosecond of latency we add to an application can impact user experience and business outcomes. An effective RASP that is too slow to be deployed is ultimately ineffective.
This brings us to today's critical topic: designing for efficiency. Our learning outcome is to design a RASP agent for minimal performance overhead using selective instrumentation, sampling, and caching strategies. We will explore the architectural patterns and trade-offs required to build a RASP that is both intelligent and fast, making it suitable for high-performance production environments.
1. The Performance Challenge of Runtime Instrumentation
A RASP agent works by embedding itself into the application's runtime. In a language like Java, this is often done using a Java Agent, a special type of program that can modify an application's bytecode as it is being loaded by the JVM.
This process of code modification, or instrumentation, is the source of all RASP's power and all its performance challenges.
The definitive guide to Java agents by Rafael Winterhalter
To understand the performance implications, let's first quickly review the core technology that enables RASP. This video from Devoxx UK provides an excellent, concise introduction to Java agents.
Please watch the following two segments: What is a Java Agent? (00:25 - 06:14): This explains the pre-main and agent-main entry points and the overall concept of attaching code to a running JVM. The Instrumentation API (07:16 - 10:03): This introduces the Instrumentation interface and the ClassFileTransformer, which is the mechanism used to modify bytecode. Focus on how a class file is essentially treated as a byte array that can be rewritten before being loaded. \nThis will give you the foundational 'first principles' understanding of how a RASP agent fundamentally operates.
The key takeaway is that instrumentation isn't free. As the video briefly mentions, adding code has several performance implications:
- CPU Overhead: The analysis logic itself (like parsing an AST) consumes CPU cycles.
- Latency: The time taken for analysis adds directly to the application's request processing time.
- Memory Overhead: The agent's code, data structures (like the
RequestContext), and any caches consume memory. - Garbage Collection (GC) Pressure: As highlighted at the end of the video (
00:28:35), the objects created by an agent can alter the application's GC behavior, potentially leading to more frequent or longer GC pauses.
Our job as architects is to design a system that mitigates these overheads. We will use a three-pronged strategy: selective instrumentation, adaptive sampling, and caching.
2. Strategy 1: Selective Instrumentation ("Be Smart About What You Inspect")
The most direct way to reduce overhead is to do less work. Instead of instrumenting every single method in an application, we should be selective and only instrument what is necessary.
There are several levels of sophistication for this strategy:
A. Static Selection (Baseline)
This is the simplest approach. The RASP is configured with a static list of "dangerous" sinks that it must always instrument. This list is derived from general security knowledge. For example:
- Java:
java.sql.Statement.execute*,java.lang.Runtime.exec,javax.naming.InitialContext.lookup(for LDAP injection). - Python:
subprocess.run,os.system,sqlite3.execute.
This is a mandatory baseline for any RASP, but we can be much smarter.
B. Vulnerability-Aware Selection
A RASP doesn't operate in a vacuum. It often exists in an ecosystem with other security tools, such as Software Composition Analysis (SCA) scanners that find vulnerabilities in third-party libraries. We can use this information to be highly selective.
Design:
- The RASP agent receives a manifest of known vulnerabilities in the application's dependencies (e.g., from an SCA tool).
- The manifest maps a CVE (Common Vulnerabilities and Exposures) to a specific vulnerable class and method (e.g., CVE-2021-44228 maps to
org.apache.logging.log4j.core.lookup.JndiLookup.lookup). - The RASP's instrumentation logic uses this manifest to only install hooks on those specific vulnerable methods. All other methods in the Log4j library remain untouched and incur zero overhead.
This turns the RASP into a highly efficient "virtual patching" system, surgically targeting only known-vulnerable code paths.
C. Adaptive Filtering (Two-Phase Monitoring)
Sometimes, risk isn't about a known CVE but about how the application uses certain functions. For example, a SQL query that doesn't use any user input is safe, while one that does is risky. We can design a RASP that adapts its instrumentation based on runtime behavior.
The PhD thesis, "Adaptive Filtering and Sampling in Runtime Software Monitoring," proposes a "two-phase" approach that serves as an excellent architectural blueprint.
[PDF] Adaptive Filtering and Sampling in Runtime Software Monitoring
This paper outlines a formal process for adaptively filtering what to monitor. It's an advanced concept that directly applies to our goal of designing a high-performance RASP.
Please read the section '1.2 Proposed Solution and Contributions Overview' (page 22). Focus on the description of the 'two-phase monitoring approach'. This section introduces the core idea of using lightweight, coarse-grained monitoring to guide a more in-depth, fine-grained monitoring phase.
Based on this model, we can design the following system:
-
Phase 1 (Coarse-Grained Monitoring):
- The RASP instruments a broad set of methods (e.g., all public methods in the data access layer).
- The instrumentation is extremely lightweight. It only collects simple metrics, such as:
- Execution frequency.
- Whether the method's parameters contain data that originated from an external HTTP request (taint tracking).
- This phase identifies methods that are both frequently called and process user-controlled data, marking them as "relevant" or "high-risk".
-
Phase 2 (Fine-Grained Monitoring):
- Only for the methods marked as "relevant" in Phase 1, the RASP activates the expensive analysis engine.
- This is where the full context capture, AST parsing, and semantic analysis we designed in the last lesson would run.
This adaptive approach ensures that the most expensive analysis is only applied where it's most needed, minimizing the performance impact on the vast majority of "safe" code paths.
3. Strategy 2: Adaptive Sampling ("Be Smart About When You Inspect")
Selective instrumentation helps us decide what to inspect. Sampling helps us decide when to inspect. Even for a risky method, we may not need to analyze every single invocation, especially under high load.
However, simple random sampling (e.g., "analyze 10% of calls") is naive. It might miss a single, critical attack, and it doesn't adapt to changing application load. We need an intelligent, adaptive approach.

The thesis by Mertz and Nunes provides a robust algorithm for this process.
[PDF] Adaptive Filtering and Sampling in Runtime Software Monitoring
The same paper that described two-phase filtering also details a complete process for adaptive sampling. This is the most detailed and practical resource for designing this part of our RASP agent.
This is a deep dive, as you prefer. Please read Chapter 5, focusing on these sections: Activity 1: Sampling Decision (page 80, Algorithm 1): Understand how it decides whether to sample a given request. Notice the check to keep the sample distribution similar to the population—this prevents over-sampling common requests. Activity 2: Sampling Rate Adaptation (page 82, Algorithm 2): This is the core of the 'adaptive' logic. See how it uses application performance (response time) to decide whether to increase or decrease the sampling rate. Activity 3: Sample Evaluation (page 85, Algorithm 3): Understand how the system periodically checks if the collected sample is statistically representative. Evaluation Results (Table 5.3, page 91): Briefly review this table. Notice how the 'ADP' (adaptive) approach finds a balance between the high overhead of 'UNI' (uniform/fixed sampling) and the poor representativeness of 'INV' (inversely proportional).
Let's summarize the design of our adaptive sampling engine based on these principles:
-
Monitor Application Performance: The RASP agent continuously tracks key performance indicators (KPIs) like request throughput and average response time. It maintains a
performanceReferencebaseline of what "normal" performance looks like. -
Dynamically Adjust Sampling Rate: A background "shepherding thread" periodically runs an adaptation algorithm (like Algorithm 2 from the paper):
- If current performance is significantly worse than the baseline, it means the application is under stress (or the RASP itself is causing too much overhead). The engine decreases the sampling rate (e.g., from 50% to 10%).
- If current performance is at or better than the baseline, the system has spare capacity. The engine can increase the sampling rate (e.g., from 10% back towards 50%) to improve security visibility.
-
Make Weighted Sampling Decisions: For each request arriving at an instrumented point, the agent makes a sampling decision (like Algorithm 1):
- It first checks against the current sampling rate (e.g., a 10% chance to proceed).
- If the random check passes, it performs a second check to ensure representativeness. If the agent has already seen thousands of requests for
/api/usersbut only two for/api/admin, it will be more likely to sample the/api/adminrequest to avoid starving rare-but-important endpoints from analysis.
This closed-loop feedback system allows the RASP to "back off" during periods of high load to preserve application performance, and "lean in" during quiet periods to maximize security coverage.
4. Strategy 3: Caching ("Don't Re-do Expensive Work")
Our final strategy is caching. The analysis we designed in the last lesson, particularly AST parsing, is computationally expensive. If we can avoid re-doing this work for identical inputs, we can achieve significant performance gains.

What Can We Cache in a RASP?
- Verdicts: The most valuable thing to cache is the final verdict. We can create a cache where the key is a hash of the user input (e.g., the SQL parameter value) and the value is the verdict (
ALLOW/BLOCK).- Flow:
- Receive input
x. - Calculate
hash(x). - Look up
hash(x)in the verdict cache. - Cache Hit: Return the cached verdict immediately.
- Cache Miss: Perform the full, expensive AST analysis on
x. Store the resulting verdict in the cache againsthash(x). Return the new verdict.
- Receive input
- Flow:
- ASTs: Parsing can be slow. If an application uses prepared statements, the SQL query template is always the same. We can parse the template once to generate a "golden" AST and cache it. Future analyses only need to parse the user-supplied values, not the entire query structure.
- Threat Intelligence Data: If the RASP performs external lookups (e.g., checking an IP address against a reputation service), the results of these lookups should be cached locally with a defined Time-To-Live (TTL) to reduce network latency.
Caching Pitfalls in a Security Context
While powerful, caching introduces its own set of challenges, especially for a security product.
Caching Pitfalls Every Developer Should Know
The ByteByteGo channel has a great video that explains common caching problems. While it speaks from a general system design perspective, these pitfalls are highly relevant to our RASP design.
Please watch the segment on 'Cache Penetration' (02:54 - 04:19). This is a critical consideration for our verdict cache. Think about how an attacker could exploit this.
As the video explains, cache penetration is a major risk. An attacker can bypass our verdict cache entirely by sending a continuous stream of unique malicious payloads. Since each payload is unique, it will always result in a cache miss, forcing our RASP to run the expensive analysis every single time, potentially leading to a denial-of-service condition.
One mitigation, also mentioned in the video, is using a Bloom filter. This is a probabilistic data structure that can tell you if an item is definitely not in a set. We could maintain a Bloom filter of all known-benign inputs. Before hitting the main cache or the analysis engine, we check the input against the Bloom filter. If it reports "definitely not benign," we can skip the verdict cache and go straight to analysis, making our system more resilient to this type of attack.
Conclusion
We've now architected the key mechanisms for building a RASP that is not only effective but also highly performant. A production-grade RASP isn't just about clever detection; it's about sophisticated engineering to manage the trade-offs between security visibility and performance overhead.
Key Takeaways:
- Performance is a primary architectural concern for a RASP, impacting latency, CPU, memory, and even GC behavior.
- Selective Instrumentation reduces overhead by targeting only what's risky, using static lists, vulnerability data, or adaptive, two-phase monitoring.
- Adaptive Sampling manages overhead under load by dynamically adjusting the analysis rate based on real-time application performance, while still aiming for a statistically representative sample.
- Caching avoids re-computing expensive analysis for repeated inputs, using patterns like cache-aside for verdicts and parsed ASTs.
- These strategies are not mutually exclusive; a robust RASP will combine all three to create a layered performance management system.
Preview of the Next Module
Throughout the last few lessons, we've designed a RASP that provides deep, in-application protection. This is a powerful, modern approach to security that sits at the very core of the application.
In the next module, we will zoom out from the application runtime to the network edge. We'll begin exploring the architecture of Unified Edge Security Platforms, which integrate services like Web Application Firewalls (WAFs), DDoS mitigation, and Bot Management into a single, cohesive system. We'll see how these different security layers—from the distant network edge to the intimate application runtime—can complement each other in a defense-in-depth strategy.