AWS Builder Center
Optimizing Amazon Keyspaces : Three Quick Fixes for Throughput and Connection Issues

Optimizing Amazon Keyspaces : Three Quick Fixes for Throughput and Connection Issues

Identify and fix the three most common performance issues in Amazon Keyspaces

What you will learn

How to identify and fix the three most common performance bottlenecks in Amazon Keyspaces table throttling, observability gaps, and connection saturation without any application code changes.

Prerequisites

  • An AWS account with an Amazon Keyspaces table in production or development
  • AWS CLI configured with appropriate IAM permissions
  • A Cassandra client driver (Java 4.x, Python, or Node.js; examples provided)
Level: 200 (Intermediate)

Background

Amazon Keyspaces is a fully managed, serverless Cassandra-compatible database service that automatically scales with your workload. However, three common configuration defaults frequently create unexpected performance ceilings that developers misinterpret as capacity issues:
  1. Provisioned capacity mode without auto scaling — Creates a hard throughput ceiling that throttles requests when exceeded
  2. Default CloudWatch dashboards — Hide partition-level and connection-level metrics, making root cause analysis difficult
  3. Driver connection pool defaults — Typically 1 connection per endpoint, capping throughput at ~3,000 ops/sec per connection
This guide walks you through each fix in order of complexity and impact.

Step 1: Eliminate Table-Level Throttling

Check If You're Affected

Open the AWS Console and navigate to CloudWatch → Metrics → Keyspaces. Look for non-zero values in:
  • ReadThrottleEvents
  • WriteThrottleEvents
If either metric is greater than zero, your table is being throttled at the capacity level.

Fix Option A: Switch to On-Demand (Best for Variable Workloads)

On-Demand mode automatically scales capacity with zero provisioning overhead.
Via AWS Console:
  1. Open Amazon Keyspaces console
  2. Select your table → Capacity tab
  3. Click On-demand
  4. Click Save
Via CQL:
1
2
ALTER TABLE my_keyspace.my_table
WITH CUSTOM_PROPERTIES = {'capacity_mode': {'throughput_mode': 'PAY_PER_REQUEST'}};
When to use: Variable or unpredictable traffic patterns, new workloads, development and test environments, rapid iteration phases.

Fix Option B: Enable Auto Scaling on Provisioned (Best for Predictable Workloads)

For workloads with predictable baseline traffic, auto scaling offers better cost control while maintaining performance.
Steps:
  1. Open Amazon Keyspaces console → select your table
  2. Navigate to Capacity tab
  3. Select Provisioned (if not already selected)
  4. Enable Auto Scaling for both Read and Write capacity
  5. Set Target utilization based on your traffic volatility; AWS default is 70% (configurable range: 20–90%). Lower percentages (e.g., 50–60%) provide more headroom for traffic spikes; higher percentages (75–90%) optimize cost for stable workloads
  6. Set Minimum capacity based on your baseline traffic
  7. Set Maximum capacity based on your peak traffic forecast
  8. Click Save
When to use: Predictable or semi-predictable workloads with a known baseline, workloads where you want to control peak costs, applications with clear daily or weekly traffic patterns.

Verification

After applying either fix, check CloudWatch metrics again. Both ReadThrottleEvents and WriteThrottleEvents should drop to zero within the next monitoring interval.

Step 2: Deploy Comprehensive Monitoring

Why This Matters

Without proper observability, you cannot distinguish between table-level throttling, hot partitions, and connection saturation they all manifest as client timeouts or latency spikes. Correct diagnosis requires partition-level and connection-level metrics.

Deploy the AWS CloudWatch Dashboard

AWS provides a pre-built CloudFormation template that creates all necessary dashboards and alarms.
Clone and deploy:
1
2
3
4
5
6
7
8
git clone https://github.com/aws-samples/amazon-keyspaces-cloudwatch-cloudformation-templates
cd amazon-keyspaces-cloudwatch-cloudformation-templates

aws cloudformation deploy \
--template-file amazon-keyspaces-cloudwatch-template.yaml \
--stack-name keyspaces-dashboard \
--parameter-overrides KeyspaceName=my_keyspace TableName=my_table \
--region us-east-1
Once deployed, open CloudWatch and navigate to Dashboards → look for the newly created dashboard.

Key Metrics to Monitor

These metrics are critical for distinguishing performance issues:
MetricThresholdMeaning
StoragePartitionThroughputCapacityExceeded> 0Hot partition detected; review your partition key design
PerConnectionRequestRateExceeded> 0Driver connection pool is saturated; increase connections per endpoint (Step 3)
SuccessfulRequestLatency (P99)> 20msPossible capacity pressure; consider increasing provisioned capacity
ReadThrottleEvents> 0Table-level read capacity exceeded
WriteThrottleEvents> 0Table-level write capacity exceeded

Recommended Alarms

Create CloudWatch alarms to proactively detect issues:
⚠️ Note: The alarm threshold values below are based on operational experience and are intended as a starting point. They are not AWS-published standards; adjust them to suit your workload’s baseline and traffic patterns.
  • WriteThrottleEvents > 100 over 5 minutes
  • StoragePartitionThroughputCapacityExceeded > 50 over 5 minutes
  • PerConnectionRequestRateExceeded > 10 over 1 minute (alert on 3 consecutive periods)

Step 3: Fix Connection Saturation

Check If You're Affected

In CloudWatch, look for PerConnectionRequestRateExceeded > 0. This indicates your driver is attempting more operations per connection than the 3,000 ops/sec limit allows.

Understand the Math

Each Cassandra connection can handle up to 3,000 CQL operations per second, though AWS recommends targeting 500 ops/sec per connection for headroom.
Default configuration:
  • Public endpoints: 9 peers
  • Default driver config: 1 connection per peer
  • Total connections: 9
  • Effective throughput ceiling: ~27,000 ops/sec (9 connections × 3,000 ops/sec each)
However, certain configurations can silently reduce your driver to a single connection, capping you at 3,000 ops/sec. The two most common causes are:
1.     TLS hostname validation enabled (Java 4.x default) - The driver sees Amazon Keyspaces as a single-node cluster because hostname validation is incompatible with the service's multi-endpoint architecture. Always set hostname-validation = false for Amazon Keyspaces.
2.     VPC endpoint policy misconfiguration - If the endpoint policy does not permit cassandra:Select on system.peers, the driver discovers only 1 endpoint and creates only 1 connection regardless of pool settings.

Calculate Your Required Connection Count

Use this formula to determine the connections-per-endpoint needed:
1
2
3
connections_per_endpoint = ceiling(
peak_ops_per_second / (app_instances × total_endpoints × 500)
)
Examples:
WorkloadPeak Ops/SecApp InstancesEndpointsConnections/Endpoint
Mobile app10,00029 (public)2
Analytics pipeline20,00029 (public)3
High-throughput service20,00023 (VPC)7

Configure Your Driver

Java Driver 4.x
Create or update application.conf:
1
2
3
4
5
6
7
8
9
10
datastax-java-driver {
advanced.connection.pool {
local.size = 3
remote.size = 3
}

advanced.ssl-engine-factory {
hostname-validation = false
}
}
⚠️ Important: Java 4.x drivers enable TLS hostname validation by default, which silently reduces your connection pool to 1. Always set hostname-validation = false for Amazon Keyspaces.
Python Driver
1
2
3
4
5
6
7
8
9
10
11
12
13
from cassandra.cluster import Cluster
from cassandra.policies import HostDistance

cluster = Cluster(
contact_points=['cassandra.us-east-1.amazonaws.com'],
port=9142
)

# Set connection pool sizes
cluster.set_core_connections_per_host(HostDistance.LOCAL, 3)
cluster.set_max_connections_per_host(HostDistance.LOCAL, 3)

session = cluster.connect()
Node.js Driver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const cassandra = require('cassandra-driver');

const client = new cassandra.Client({
contactPoints: ['cassandra.us-east-1.amazonaws.com'],
localDataCenter: 'us-east-1',
protocolOptions: { port: 9142 },
pooling: {
coreConnectionsPerHost: {
[cassandra.types.distance.local]: 3,
[cassandra.types.distance.remote]: 3
}
}
});

client.connect();

Verification

Deploy your updated driver configuration and monitor CloudWatch. The PerConnectionRequestRateExceeded metric should drop to 0 within 5 minutes and remain at zero during normal operation.

Special Case: VPC Endpoint Considerations

If your application connects to Keyspaces through VPC endpoints, two important differences apply:

1. Fewer Peers

VPC endpoints expose 2–5 endpoints (most commonly 3, up to 5 in us-east-1) instead of the 9 available on the public endpoint. This reduces the connection distribution and requires more connections per endpoint to compensate.
Verify with:
1
SELECT * FROM system.peers;
If this returns fewer rows than expected, you're limited to a smaller endpoint pool.

2. Endpoint Policy Restrictions

If your IAM entity lacks EC2 permissions (ec2:DescribeNetworkInterfaces, ec2:DescribeVpcEndpoints), the system.peers table will be empty, causing the driver to see only 1 endpoint and create only 1 connection, regardless of your pool configuration. Ensure your execution environment has the necessary EC2 permissions for VPC endpoint discovery.
Check your VPC endpoint policy and ensure it includes:
1
2
3
4
5
{
"Effect": "Allow",
"Action": "cassandra:Select",
"Resource": "*"
}

What's Next

After resolving these three issues, if you still observe throttling events, the likely culprit is a hot partition indicated by StoragePartitionThroughputCapacityExceeded > 0 in CloudWatch.
Hot partitions require data model review to balance traffic across your partition key space. See the Data Modeling Best Practices  guide.

References

Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article