# SysPad component catalog (96 types)

Config keys for every SysPad component `type`. Use with the format quickstart at
https://syspad.io/spec . Import finished files at https://syspad.io .

Each entry: `type` then its config keys as `key: type = default`. `[a|b]` lists allowed enum values;
`(min..max)` shows numeric range. Instance-type enums are large, so a representative default is
shown; any valid instance id for that service is accepted. Distributors split traffic; messaging
nodes are async boundaries (a synchronous request completes when it reaches one).

## Compute
- `ec2` (EC2) instance-typed: `instanceType=m6i.xlarge` | `instanceCount: number = 1 (1..1000)` | `avgRequestMs: number = 20` | `threadsPerVCPU: number = 10` | `connectionsPerInstance: number = 10` (DB pool held per instance; total held = instances × this)
- `lambda` (AWS Lambda): `memoryMb: enum = 1024` | `avgDurationMs: number = 50` | `concurrencyLimit: number = 1000` | `runtime: enum = nodejs20 [nodejs18|nodejs20|python312|java21|java17|dotnet8|go|ruby]` | `coldStartEnabled: boolean = true` | `invocationsPerMonth: number = 10000000`
- `ecs-fargate` (ECS Fargate): `taskConfig: enum = 1vCPU-2GB` | `taskCount: number = 2` (floor when auto-scaling on) | `autoScaling: boolean = false` | `maxTaskCount: number = 10` | `targetUtilizationPct: number = 70` | `avgRequestMs: number = 20` | `threadsPerVCPU: number = 10` | `connectionsPerInstance: number = 10` (DB pool per task)
- `ecs-ec2` (ECS on EC2) instance-typed: `instanceType=m6i.xlarge` | `instanceCount: number = 3` | `taskVcpu: number = 0.5` (bin-packing; a size that doesn't divide the host vCPU strands the remainder) | `avgRequestMs: number = 20` | `threadsPerVCPU: number = 10` | `connectionsPerInstance: number = 10` (DB pool per host)
- `eks` (EKS Cluster) instance-typed: `nodeInstanceType=m6i.xlarge` | `nodeCount: number = 3` | `minReplicas: number = 2` | `maxReplicas: number = 10` | `targetCpuUtilizationPct: number = 70` | `podCpu: number = 0.5` | `avgRequestMs: number = 20` | `threadsPerPod: number = 10` | `connectionsPerInstance: number = 10` (DB pool per pod)
- `eks-fargate` (EKS on Fargate): `podSize: enum = 0.5vCPU-1GB` | `replicas: number = 4` (floor when HPA on) | `autoScaling: boolean = false` (HPA) | `maxReplicas: number = 20` | `targetUtilizationPct: number = 70` | `avgRequestMs: number = 20` | `threadsPerVCPU: number = 10` | `connectionsPerInstance: number = 10` (DB pool per pod)
- `aws-batch` (AWS Batch): `computeEnv: enum = ec2 [ec2|fargate|fargate-spot]` | `vcpusPerJob: number = 1` | `maxVcpus: number = 256` | `avgJobDurationSec: number = 60`
- `app-runner` (App Runner) DEPRECATED by AWS (closed to new customers 2026-04; use `ecs-fargate` for new designs): `size: enum = 1vCPU-2GB [0.25vCPU-0.5GB|0.5vCPU-1GB|1vCPU-2GB|2vCPU-4GB|4vCPU-8GB]` | `maxConcurrency: number = 100` | `maxInstances: number = 25` | `avgRequestMs: number = 50`
- `step-functions` (Step Functions): `workflowType: enum = standard [standard|express]` | `statesPerExecution: number = 8` | `avgStateMs: number = 50`
- `mwaa` (MWAA - managed Apache Airflow) instance-typed: `environmentSize: enum = mw1.small [mw1.small|mw1.medium|mw1.large]` | `maxWorkers: number = 10 (1..25)` | `tasksPerDagRun: number = 10` | `avgTaskDurationSec: number = 30` | `metaDbStorageGb: number = 20`

## Database
- `rds` (RDS) instance-typed: `instanceType=db.m6i.large` | `engine: enum = mysql [mysql|postgres|mariadb]` | `multiAz: boolean = false` | `readReplicas: number = 0 (0..5)` | `readPct: number = 80` | `avgQueryMs: number = 5` | `storageGib: number = 100` | `iops: number = 3000` | `maxConnectionsOverride: number = 0` (0 = derive max_connections from instance memory)
- `rds-proxy` (RDS Proxy): `dbVcpus: number = 4` | `poolSize: number = 100` | `backendQueryMs: number = 5` | `pinningPct: number = 5` | `addedLatencyMs: number = 2`
- `aurora` (Aurora) instance-typed: `instanceType=db.r6g.large` | `serverlessV2: boolean = false` | `maxAcu: number = 16` | `readReplicas: number = 1 (0..15)` | `readPct: number = 80` | `avgQueryMs: number = 3` | `engine: enum = aurora-mysql [aurora-mysql|aurora-postgresql]` | `ioOptimized: boolean = false` (drops per-I/O charge for ~30% higher compute; a cost crossover vs Standard) | `maxConnectionsOverride: number = 0` (0 = derive from memory/ACUs)
- `dynamodb` (DynamoDB): `capacityMode: enum = on-demand [on-demand|provisioned]` | `provisionedWcu: number = 1000` | `provisionedRcu: number = 5000` | `readPct: number = 80` | `consistentReads: boolean = false` | `avgItemSizeKb: number = 1` | `hotKeyTrafficPct: number = 0` (share of traffic on the single hottest partition key; a skewed key throttles at the per-partition 3,000 RCU/s | 1,000 WCU/s ceiling) | `storageGib: number = 50` (model DAX by wiring the separate `dynamodb-dax` component in front of the table)
- `dynamodb-dax` (DAX) instance-typed: `nodeType=dax.r5.large` | `nodeCount: number = 3 (1..11)` | `cacheHitRate: number = 90` | `writePct: number = 0` (write-through: writes bypass the cache, hit the single primary, and always reach DynamoDB)
- `elasticache-redis` (ElastiCache) instance-typed: `engine: enum = valkey [valkey|redis-oss]` | `instanceType=cache.r6g.large` | `clusterMode: boolean = false` | `shards: number = 1` | `replicasPerShard: number = 1` | `cacheHitRate: number = 85` | `workingSetGib: number = 4` (eviction drops the effective hit rate when > usable node memory) | `avgCommandUs: number = 200`
- `elasticache-memcached` (ElastiCache Memcached) instance-typed: `instanceType=cache.r6g.large` | `nodeCount: number = 3` | `cacheHitRate: number = 85` | `workingSetGib: number = 4` (eviction when > usable cluster memory)
- `memorydb` (MemoryDB) instance-typed: `nodeType=db.r6g.large` | `shards: number = 2` | `replicasPerShard: number = 1` | `readPct: number = 80`
- `documentdb` (DocumentDB) instance-typed: `instanceType=db.r6g.large` | `replicas: number = 2 (0..15)` | `readPct: number = 80` | `avgQueryMs: number = 6` | `storageGib: number = 100`
- `neptune` (Neptune) instance-typed: `instanceType=db.r6g.large` | `replicas: number = 1 (0..15)` | `readPct: number = 85` | `avgQueryMs: number = 15` | `storageGib: number = 100`
- `keyspaces` (Keyspaces): `capacityMode: enum = on-demand [on-demand|provisioned]` | `provisionedWcu: number = 1000` | `provisionedRcu: number = 3000` | `readPct: number = 80` | `quorumReads: boolean = true` | `avgRowSizeKb: number = 1` | `storageGib: number = 50`
- `timestream` (Timestream): `writePct: number = 90` | `avgRecordSizeKb: number = 1` | `memoryStoreHours: number = 12` | `magneticStoreGib: number = 500` | `avgQueryScanMb: number = 10`
- `redshift` (Redshift) instance-typed: `serverless: boolean = false` | `baseRpu: number = 32` | `nodeType: enum = ra3.xlplus [ra3.large|ra3.xlplus|ra3.4xlarge|ra3.16xlarge|dc2.large|dc2.8xlarge|rg.xlarge|rg.4xlarge]` | `nodeCount: number = 2` | `avgQueryMs: number = 2000` | `managedStorageTb: number = 10` | `concurrencyScaling: boolean = false`
- `opensearch` (OpenSearch) instance-typed: `nodeType=r6g.large.search` | `nodeCount: number = 3` | `replicaCount: number = 1` | `searchPct: number = 75` | `storageGib: number = 100`

## Networking
- `alb` (Application Load Balancer) distributor: `azCount: number = 2 (1..6)` | `tlsEnabled: boolean = true` | `avgConnectionMs: number = 1000` | `avgPayloadKb: number = 10` | `ruleCount: number = 5`
- `nlb` (Network Load Balancer) distributor: `azCount: number = 2` | `protocol: enum = TCP [TCP|UDP|TLS|TCP_UDP]` | `avgConnectionMs: number = 10000` | `avgPayloadKb: number = 50`
- `api-gateway` (Amazon API Gateway) distributor: `apiType: enum = rest [rest|http|websocket]` | `throttleRps: number = 10000` | `burstLimit: number = 5000` | `cachingEnabled: boolean = false` (REST only) | `cacheHitRate: number = 30` (REST only) | `authorizerType: enum = none [none|iam|cognito|jwt|lambda]` | `avgMessagesPerConn: number = 50` (WebSocket only) | `avgMessageKb: number = 1` (WebSocket only). Legacy ids `api-gateway-rest` / `-http` / `-websocket` still load as aliases.
- `appsync` (AppSync): `resolversPerRequest: number = 2` | `avgResolverMs: number = 15` | `cachingEnabled: boolean = false` | `cacheHitRate: number = 50`
- `cloudfront` (CloudFront): `cacheHitRate: number = 80` | `defaultTtlSeconds: number = 86400` | `compressionEnabled: boolean = true` | `wafEnabled: boolean = false` | `avgObjectSizeKb: number = 50` | `originLatencyMs: number = 30`
- `route53` (Route 53) distributor: `maxQps: number = 10000` | `routingPolicy: enum = simple [simple|weighted|latency|failover|geolocation|multivalue]` | `healthChecksEnabled: boolean = false` | `healthCheckCount: number = 2`
- `nat-gateway` (NAT Gateway): `azCount: number = 2` | `avgPayloadKb: number = 20`
- `transit-gateway` (Transit Gateway): `attachments: number = 2` | `avgPayloadKb: number = 20`
- `global-accelerator` (Global Accelerator): `dtPremiumPerGb: number = 0.015` | `avgPayloadKb: number = 20`
- `vpc-endpoint` (PrivateLink): `azCount: number = 2` | `avgPayloadKb: number = 20`
- `direct-connect` (Direct Connect): `portSpeed: enum = "10 Gbps" [1 Gbps|10 Gbps|100 Gbps]` | `dtoPerGb: number = 0.02` | `avgPayloadKb: number = 20`
- `gwlb` (Gateway Load Balancer): `avgPayloadKb: number = 20` | `inspectionMs: number = 1`
- `internet-gateway` (Internet Gateway): no config. Free, unbounded VPC front door; private-subnet egress uses `nat-gateway` instead.
- `edge-functions` (Edge Functions on CloudFront): `runtime: enum = cloudfront-functions [cloudfront-functions|lambda-edge]` | `avgDurationMs: number = 0.5` | `memoryMb: number = 128 (128..3008)`

## Storage
- `s3` (S3): `storageClass: enum = standard [standard|standard-ia|glacier-instant|glacier-flexible|express-one-zone]` | `prefixSharding: boolean = true` | `readPct: number = 90` | `avgObjectSizeKb: number = 100` | `storageTb: number = 1` | `transferAcceleration: boolean = false`
- `ebs` (EBS): `volumeType: enum = gp3 [gp3|gp2|io2|st1]` | `provisionedIops: number = 3000` | `avgIoSizeKb: number = 16` | `sizeGib: number = 500`
- `efs` (EFS): `throughputMode: enum = elastic [elastic|provisioned|bursting]` | `provisionedMbps: number = 100` | `avgFileOpKb: number = 64` | `readPct: number = 70` | `storageGib: number = 500` | `storageClass: enum = standard [standard|infrequent-access]`
- `fsx` (FSx): `fileSystemType: enum = lustre [lustre|windows|ontap|openzfs]` | `provisionedMbps: number = 512` | `avgFileOpKb: number = 128` | `storageTib: number = 4`
- `s3-glacier` (S3 Glacier): `storageClass: enum = flexible-retrieval [instant-retrieval|flexible-retrieval|deep-archive]` | `retrievalTier: enum = standard [expedited|standard|bulk]` | `storageTb: number = 10` | `avgObjectMb: number = 100`
- `storage-gateway` (Storage Gateway): `gatewayType: enum = s3-file [s3-file|volume|tape]` | `uploadBandwidthMbps: number = 100` | `cacheHitRate: number = 70` | `avgObjectKb: number = 256`

## Messaging (async boundaries)
- `sqs` (SQS): `queueType: enum = standard [standard|fifo|fifo-high-throughput]` | `batchSize: number = 1` | `visibilityTimeoutSec: number = 30` | `retentionDays: number = 4` | `dlqEnabled: boolean = true`
- `sns` (SNS): `subscriberCount: number = 2` | `subscriberType: enum = sqs [sqs|lambda|http|email|sms]` | `messageFilterEnabled: boolean = false`
- `kinesis` (Kinesis Data Streams): `capacityMode: enum = provisioned [provisioned|on-demand]` | `shardCount: number = 4` | `avgRecordKb: number = 1` | `consumerCount: number = 1` | `enhancedFanout: boolean = false` | `retentionHours: number = 24`
- `kinesis-firehose` (Firehose): `destination: enum = s3 [s3|redshift|opensearch|splunk]` | `avgRecordKb: number = 1` | `bufferIntervalSec: number = 60` | `transformEnabled: boolean = false`
- `msk` (Amazon MSK): `brokerInstance: enum = kafka.m5.large [kafka.m5.large|kafka.m5.xlarge|kafka.m5.2xlarge|kafka.m5.4xlarge]` | `brokerCount: number = 3` | `replicationFactor: number = 3` | `avgMessageKb: number = 1`
- `amazon-mq` (Amazon MQ): `engine: enum = rabbitmq [activemq|rabbitmq]` | `instanceType: enum = mq.m5.large [mq.t3.micro|mq.m5.large|mq.m5.xlarge|mq.m5.2xlarge]` | `deploymentMode: enum = active-standby [single|active-standby|cluster]`
- `eventbridge` (EventBridge): `maxEventsPerSec: number = 10000` | `ruleCount: number = 5` | `avgTargetsPerRule: number = 1` | `schemaDiscovery: boolean = false`
- `redis-stream` (Redis Streams) instance-typed: `instanceType=cache.r6g.large` | `consumerGroups: number = 1` | `replicas: number = 1` | `maxLen: number = 1000000` | `avgMessageKb: number = 1`
- `ses` (Amazon SES): `sendRateQuota: number = 14 (1..10000)` | `emailsPerRequest: number = 1 (1..100)`
- `iot-core` (AWS IoT Core): `maxPublishRps: number = 20000` | `deviceCount: number = 10000` | `ruleMatchPct: number = 100` | `actionsPerRule: number = 1`
- `eventbridge-scheduler` (EventBridge Scheduler): `scheduleType: enum = rate [cron|rate|one-time]` | `maxInvocationRps: number = 1000`

## Analytics
- `athena` (Athena): `dataScannedMb: number = 100` | `avgQueryMs: number = 2000` | `concurrency: number = 20`
- `glue` (Glue) async boundary: `dpus: number = 10` | `avgRecordMs: number = 20`
- `emr` (EMR) instance-typed: `instanceType=m6i.xlarge` | `coreNodes: number = 2` | `avgTaskMs: number = 200`
- `quicksight` (QuickSight, BI terminus - human-facing, not request-path): `authors: number = 2` | `readers: number = 20` | `spiceGb: number = 20`

## AI / ML
- `sagemaker` (SageMaker Endpoint) instance-typed: `instanceType=ml.m5.large` | `instanceCount: number = 1` | `workers: number = 2` | `avgInferenceMs: number = 50`
- `bedrock` (Amazon Bedrock): `inputTokens: number = 500` | `outputTokens: number = 300` | `pricePer1kInput: number = 0.003` | `pricePer1kOutput: number = 0.015` | `msPerOutputToken: number = 8` | `rpmQuota: number = 1000`

## Security
- `waf` (WAF): `ruleCount: number = 5` | `managedRuleGroups: number = 1` | `rateLimitEnabled: boolean = true` | `blockRate: number = 1`
- `cognito` (Cognito): `operationType: enum = sign-in [sign-in|token-refresh|sign-up]` | `maxOpsPerSec: number = 25` | `mau: number = 10000` | `advancedSecurity: boolean = false` | `mfaEnabled: boolean = false`
- `kms` (AWS KMS - account-wide regional request quota): `requestQuota: number = 5500 (5500..100000)` | `dataKeyCacheHitPct: number = 0 (0..99.9)` | `keyCount: number = 2`
- `secrets-manager` (Secrets Manager): `secretCount: number = 5` | `cacheHitPct: number = 99 (0..99.9)`

## Observability
- `cloudwatch` (CloudWatch, async cost sink - never a throughput bottleneck): `logBytesPerRequest: number = 2 (KB)` | `retentionDays: number = 30` | `customMetrics: number = 20`

## External / third-party
- `kong` (Kong Gateway) distributor: `deployment: enum = self-hosted [self-hosted|konnect]` | `nodeCount: number = 2` | `maxRpsPerNode: number = 10000` | `addedLatencyMs: number = 2` | `monthlyCost: number = 0`
- `redis` (Redis, self-managed): `engine: enum = valkey [valkey|redis-oss]` | `maxOpsPerSec: number = 200000` | `replicas: number = 1` | `cacheHitRate: number = 85` | `monthlyCost: number = 0` | `avgCommandUs: number = 200`
- `cloudflare` (Cloudflare): `plan: enum = pro [free|pro|business|enterprise]` | `cacheHitRatio: number = 70` | `edgeLatencyMs: number = 15`
- `stripe` (Stripe): `avgLatencyMs: number = 250` | `maxRps: number = 100` | `costPerThousand: number = 0`
- `auth0` (Auth0): `plan: enum = essential [free|essential|professional|enterprise]` | `avgLatencyMs: number = 120`
- `snowflake` (Snowflake): `warehouseSize: enum = small [x-small|small|medium|large|x-large]` | `activeHoursPerDay: number = 8` | `queryLatencyMs: number = 800`
- `databricks` (Databricks): `clusterSize: enum = medium [small|medium|large|x-large]` | `activeHoursPerDay: number = 8` | `queryLatencyMs: number = 1200`
- `bigquery` (BigQuery): `avgGbScannedPerQuery: number = 1` | `queryLatencyMs: number = 1500`
- `openai` (OpenAI API): `model: enum = gpt-4o-mini [gpt-4o|gpt-4o-mini|gpt-4-turbo]` | `avgInputTokens: number = 1000` | `avgOutputTokens: number = 500` | `avgLatencyMs: number = 1500` | `maxRps: number = 500`
- `anthropic` (Anthropic / Claude): `tier: enum = sonnet [haiku|sonnet|opus]` | `avgInputTokens: number = 1000` | `avgOutputTokens: number = 500` | `avgLatencyMs: number = 1800` | `maxRps: number = 500`
- `mongodb-atlas` (MongoDB Atlas): `tier: enum = M30 [M10|M20|M30|M40]` | `avgQueryMs: number = 5`
- `planetscale` (PlanetScale): `plan: enum = scaler [scaler|scaler-pro|enterprise]` | `avgQueryMs: number = 4`
- `tiger` (Tiger / TimescaleDB): `serviceSize: enum = medium [small|medium|large|xlarge]` | `avgQueryMs: number = 5` | `compression: boolean = true`
- `redis-cloud` (Redis Cloud): `size: enum = 5gb [1gb|5gb|25gb|50gb]` | `avgLatencyMs: number = 1`
- `external-service` (generic third-party / black box): `addedLatencyMs: number = 50` | `maxRps: number = 10000` | `monthlyCost: number = 0`
- `firebase` (Firebase / Firestore - bills per DOCUMENT read): `readWriteRatio: number = 80 (%)` | `docsPerOperation: number = 5`
- `supabase` (Supabase - plan-priced Postgres): `plan: enum = free [free|pro|pro-xl|pro-4xl]` | `avgQueryMs: number = 8`
- `vercel` (Vercel - frontend hosting + functions): `plan: enum = hobby [hobby|pro]` | `functionSharePct: number = 30 (%)` | `avgFunctionMs: number = 60`
- `neon` (Neon serverless Postgres - scale-to-zero): `plan: enum = free [free|launch|scale]` | `avgQueryMs: number = 5` | `activeHoursPerDay: number = 8`
- `twilio` (Twilio SMS, async - carrier-throughput bound): `senderType: enum = long-code [long-code|short-code]` | `senderCount: number = 5`
- `algolia` (Algolia instant search): `searchesPerRequest: number = 3 (1..20)`
- `datadog` (Datadog, async cost sink): `hosts: number = 10` | `apmEnabled: boolean = true` | `logBytesPerRequest: number = 2 (KB)` | `indexedPct: number = 25 (%)`
- `temporal` (Temporal - durable workflow engine, Cloud or self-hosted): `deployment: enum = cloud [cloud|self-hosted]` | `maxActionsPerSec: number = 400 (APS)` | `activitiesPerWorkflow: number = 8` | `avgActivityMs: number = 50` | `monthlyCost: number = 300` (self-hosted only; Cloud bills per Action at $50/M)
- `dagster` (Dagster+ - data-orchestration DAG runs): `plan: enum = starter [solo|starter|pro|enterprise]` | `opsPerRun: number = 10` | `avgOpDurationSec: number = 20`
- `dkron` (Dkron - distributed cron scheduler, self-hosted): `nodeCount: number = 3` | `jobsPerNode: number = 100 (jobs/s)` | `addedLatencyMs: number = 5` | `monthlyCost: number = 90`

## Entry points (traffic sources - no inputs, emit the simulated RPS, cost nothing)
- `users` (Users): no config. Rename the node's label (e.g. "Web App", "Mobile App") to signal client type - simulation is identical either way.

## Generic shapes (annotation only, not simulated)
- `shape-rectangle`, `shape-circle`, `shape-diamond`, `shape-text`: no config. Use `label` for the text.
