apache/cassandra · warning
prepared statements discarded in the last minute because…
Error message
{} prepared statements discarded in the last minute because cache limit reached ({} MiB) What it means
QueryProcessor's scheduled task warns when prepared statements had to be evicted from the in-memory prepared-statement cache during the last minute because the cache hit its configured size limit (prepared_statements_cache_size_mb). Evicted statements must be re-prepared by clients, adding latency and load.
Solutions
- Increase prepared_statements_cache_size_mb in cassandra.yaml (or set to 0 for auto heuristic) and restart
- Fix clients to use bind variables/parameters instead of string-interpolated unique queries
- Monitor statement churn and reduce per-partition key IN lists that expand into many unique statements
Example fix
# cassandra.yaml # before prepared_statements_cache_size_mb: 16 # after prepared_statements_cache_size_mb: 256
Defensive patterns
Strategy: validation
Validate before calling
// Client-side: detect query-shape churn
const uniqueTemplates = new Set();
function guard(query) {
const tpl = query.replace(/\d+/g, '?').replace(/'[^']*'/g, '?');
if (uniqueTemplates.size > 10000) throw new Error('statement churn too high');
uniqueTemplates.add(tpl);
} Prevention
- Always use bind markers instead of string interpolation
- Size prepared_statements_cache_size_mb above your actual unique statement count
- Alert on this warning in log monitoring; it indicates client-side query design issues
When it happens
Trigger: Client drivers preparing more unique statements than fit in DatabaseDescriptor.getPreparedStatementsCacheSizeMiB(); the per-minute scheduled job in QueryProcessor detects evictions > 0 and logs the warning.
Common situations: Applications generating unbounded unique statements (e.g. concatenating IDs/values into query text instead of using bind markers); undersized cache after a client fleet growth; burst of new schema/queries.
Related errors
- Prepared statement of size
- Prepared statements for other than modification and…
- The query contains only literal values and no bind markers…
- `USE ` with prepared statements is considered to be an…
- A TTL must be greater or equal to 0, but was
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/7241951e1d977a10.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/QueryProcessor.java:153
// Size of the prepared statement cache in bytes.
public static long PREPARED_STATEMENT_CACHE_SIZE_BYTES = capacityToBytes(DatabaseDescriptor.getPreparedStatementsCacheSizeMiB());
private static final AtomicInteger lastMinuteEvictionsCount = new AtomicInteger(0);
static
{
preparedStatements = Caffeine.newBuilder()
.executor(ImmediateExecutor.INSTANCE)
.maximumWeight(PREPARED_STATEMENT_CACHE_SIZE_BYTES)
.weigher(QueryProcessor::getSizeOfPreparedStatementForCache)
.removalListener((key, prepared, cause) -> evictPreparedStatement(key, cause))
.build();
ScheduledExecutors.scheduledTasks.scheduleAtFixedRate(() -> {
long count = lastMinuteEvictionsCount.getAndSet(0);
if (count > 0)
logger.warn("{} prepared statements discarded in the last minute because cache limit reached ({} MiB)",
count,
DatabaseDescriptor.getPreparedStatementsCacheSizeMiB());
}, 1, 1, TimeUnit.MINUTES);
logger.info("Initialized prepared statement caches with {} MiB",
DatabaseDescriptor.getPreparedStatementsCacheSizeMiB());
}
private static void evictPreparedStatement(MD5Digest key, RemovalCause cause)
{
if (cause.wasEvicted())
{
metrics.preparedStatementsEvicted.inc();
lastMinuteEvictionsCount.incrementAndGet();
SystemKeyspace.removePreparedStatement(key);
}
}
View on GitHub (pinned to 88fd0f6a0e)