Guide · AWS MSK Serverless
MSK Serverless for MCP Servers — Capacity Model, IAM-Only Auth, and Probe Pipeline Trade-offs
MSK Serverless removes partition pre-provisioning: you create topics without specifying shard counts and AWS scales the underlying storage and throughput automatically up to a per-cluster quota of 200 MiBps ingress and 400 MiBps egress. For MCP probe pipelines with bursty ingest — many probes completing simultaneously during a scan wave — this eliminates the capacity-planning loop that plagues provisioned MSK clusters. The catch is that MSK Serverless enforces IAM authentication only; SCRAM credentials and mTLS certificate auth are not supported. Every producer and consumer must use the SASL_SSL protocol with sasl.mechanism=AWS_MSK_IAM and a valid IAM role. If your existing Kafka clients use SCRAM or username/password auth, migration to MSK Serverless requires a client-side change before you can connect at all.
TL;DR
MSK Serverless is the right choice when your probe ingest volume is unpredictable and you do not want to size broker counts and partition counts in advance. Use provisioned MSK when you need custom topic-level configs (retention.ms overrides, log compaction), MSK Connect sink connectors, or MSK Replication — none of those features are available on MSK Serverless. Authentication is IAM-only; plan the IAM principal and policy before cluster creation. Pricing is per-GiB-hour of partition storage plus per-MB of data ingressed and egressed — there are no broker-hour charges.
Capacity model: how throughput scales without partition management
On a provisioned MSK cluster, throughput is bounded by (broker count) × (per-broker throughput ceiling). You plan ahead: N brokers × M topics × P partitions. MSK Serverless replaces that model with a single per-cluster soft quota:
| Metric | MSK Serverless default quota | Provisioned MSK (comparison) |
|---|---|---|
| Ingress throughput | 200 MiBps per cluster | Scales with broker count and instance type |
| Egress throughput | 400 MiBps per cluster | Scales with broker count and instance type |
| Partitions per cluster | Up to 120 partitions (soft) | Up to 300,000 partitions (depends on instance) |
| Topic-level retention overrides | Not supported | Supported per topic via configuration |
| Partition rebalancing | Automatic | Manual (rack-aware assignment) |
For AliveMCP, the probe pipeline produces one Kafka message per probe completion — typically 1–4 KB of JSON containing endpoint ID, HTTP status, response time, and tool-schema hash. At 2,000 probe completions per second that is roughly 8 MiBps ingress, well within the 200 MiBps quota. The 120-partition soft limit is the binding constraint for scale-out: if the probe worker fleet grows beyond ~120 concurrent consumer threads and each needs its own partition for ordered processing, you will need provisioned MSK.
IAM-only authentication: required configuration
MSK Serverless enforces SASL/IAM for all clients. There is no option to enable unauthenticated, SCRAM, or mTLS access. Every producer and consumer needs:
- A boto3 or AWS SDK credential chain (instance profile, ECS task role, Lambda execution role, or explicit access key)
- The
aws-msk-iam-authlibrary (Java) or a compatible SASL/IAM plugin for the client language - An IAM policy granting
kafka-cluster:Connect,kafka-cluster:DescribeGroup,kafka-cluster:AlterGroup,kafka:DescribeTopic,kafka-cluster:ReadData, and/orkafka-cluster:WriteDataon the cluster and topic ARNs
# Node.js producer with MSK IAM auth (using kafkajs + msk-iam-auth-library)
import { Kafka } from 'kafkajs';
import { MSKAuthProvider } from 'aws-msk-iam-sasl-signer-js';
const kafka = new Kafka({
clientId: 'alivemcp-probe-producer',
brokers: ['b-1.cluster.msk.us-east-1.amazonaws.com:9098'],
ssl: true,
sasl: {
mechanism: 'oauthbearer',
oauthBearerProvider: async () => {
const provider = new MSKAuthProvider({ region: 'us-east-1' });
const token = await provider.generateAuthToken();
return { value: token };
},
},
});
The IAM token has a 15-minute expiry. The MSKAuthProvider re-fetches a token before each connection and on token expiry — your probe worker does not need a refresh loop. On Lambda, the execution role is the IAM principal; the SDK credential chain resolves it automatically.
Minimum IAM policy for a probe result producer
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"kafka-cluster:Connect",
"kafka-cluster:DescribeTopic",
"kafka-cluster:WriteData"
],
"Resource": [
"arn:aws:kafka:us-east-1:123456789012:cluster/alivemcp-probe-results/*",
"arn:aws:kafka:us-east-1:123456789012:topic/alivemcp-probe-results/*/probe-results"
]
}
]
}
Tiered storage: default on Serverless
MSK Serverless uses tiered storage by default. Data is written to local broker SSD first, then offloaded to S3-backed tiered storage. There is no fixed local storage limit — the cluster will not fill a disk. Retention is controlled at the cluster level via the log.retention.ms default (7 days). You cannot override retention.ms per-topic on MSK Serverless — all topics share the cluster-level retention.
For AliveMCP probe result topics, 7-day retention covers the DLQ replay window (probe results are archived to S3 via a separate archiver consumer within 1 hour; the Kafka retention is an emergency replay buffer). If you need per-topic retention tuning — for example, a 1-day topic for ephemeral probe commands and a 30-day topic for historical raw results — you need provisioned MSK with topic-level configs.
What MSK Serverless does NOT support
| Feature | MSK Serverless | Provisioned MSK |
|---|---|---|
| MSK Connect (S3 Sink, DynamoDB Sink) | Not available | Available |
| MSK Replication (cross-region DR) | Not available | Available |
| Log compaction | Not available | Available per topic |
| Per-topic retention.ms override | Not available (cluster-level only) | Available |
| SCRAM / mTLS auth | Not available (IAM only) | Available |
| Custom broker config (e.g., message.max.bytes) | Not available | Available via configuration versions |
| Tiered storage | Always on | Optional (must enable) |
CDK provisioning for MSK Serverless
MSK Serverless uses the L1 construct CfnServerlessCluster — there is no L2 wrapper yet. The cluster creation includes an inline VPC config and security group, and a client authentication block that enforces IAM.
import * as cdk from 'aws-cdk-lib';
import { aws_msk as msk, aws_ec2 as ec2 } from 'aws-cdk-lib';
const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: false });
const mskSg = new ec2.SecurityGroup(this, 'MskSg', {
vpc,
description: 'MSK Serverless probe results',
allowAllOutbound: true,
});
// Allow probe workers (in their own SG) to reach MSK on port 9098
mskSg.addIngressRule(probeWorkerSg, ec2.Port.tcp(9098), 'Kafka SASL/TLS');
const serverlessCluster = new msk.CfnServerlessCluster(this, 'ProbeCluster', {
clusterName: 'alivemcp-probe-results',
vpcConfigs: [{
subnetIds: vpc.privateSubnets.map(s => s.subnetId),
securityGroups: [mskSg.securityGroupId],
}],
clientAuthentication: {
sasl: { iam: { enabled: true } },
},
});
new cdk.CfnOutput(this, 'ClusterArn', { value: serverlessCluster.attrArn });
CloudWatch metrics for MSK Serverless
MSK Serverless emits a subset of the metrics available on provisioned clusters. Key metrics for probe pipeline monitoring:
| Metric | Namespace | What to alarm on |
|---|---|---|
BytesInPerSec | AWS/Kafka | > 180 MiBps sustained (near 200 MiBps quota) |
BytesOutPerSec | AWS/Kafka | > 360 MiBps sustained (near 400 MiBps quota) |
OffsetLag | AWS/Kafka | Increasing lag on probe-result consumer group |
FetchMessageConversionsPerSec | AWS/Kafka | High value indicates message format conversion overhead |
ProduceTotalTimeMsMean | AWS/Kafka | > 100ms for probe result writes warrants investigation |
Note: UnderReplicatedPartitions is not meaningful for MSK Serverless (replication is managed by AWS). Do not build alarms on it for serverless clusters — it will always read 0.
Common failure modes
| Symptom | Cause | Fix |
|---|---|---|
Producer fails to connect: SASL handshake failed | Client is using SCRAM or PLAIN mechanism — not supported on MSK Serverless | Switch to sasl.mechanism=AWS_MSK_IAM (OAUTHBEARER) with MSKAuthProvider |
Producer fails with TopicAuthorizationException | IAM policy missing kafka-cluster:WriteData on topic ARN | Add topic-level WriteData action; cluster-level allow is insufficient |
| Throughput capped at ~200 MiBps with retries | Per-cluster ingress quota reached | Throttle probe scan rate, or migrate to provisioned MSK with higher broker count |
| Partition count hits 120 soft limit | Too many topics × partitions | Consolidate topics; or request quota increase via AWS Support |
| Unable to create MSK Connect connector | MSK Connect not supported on Serverless | Use a consumer application to write to S3/DynamoDB, or migrate to provisioned MSK |