references/getting-started/instructions.md
# Getting Started & Setup
## When to Activate
User wants to create a new Timestream for InfluxDB instance or cluster, connect to an existing one, choose between engine versions, or configure authentication.
## Workflow
### 1. Determine Engine Version
Ask the user one question: "Are you starting a new project or working with an existing InfluxDB deployment?"
- **New project** → Recommend InfluxDB 3 (SQL support, Processing Engine, better high-cardinality handling)
- **Existing V2 deployment** → Stay on V2 unless they want to migrate (route to `migration`)
- **Need read scaling** → InfluxDB 2 Read Replica Clusters (requires Marketplace subscription)
### 2. Provision
**InfluxDB 2 (standalone instance):**
```bash
aws timestream-influxdb create-db-instance \
--name my-influxdb \
--db-instance-type db.influx.large \
--db-storage-type InfluxIOIncludedT1 \
--allocated-storage 400 \
--deployment-type SINGLE_AZ \
--vpc-subnet-ids subnet-abc \
--vpc-security-group-ids sg-abc \
--db-parameter-group-identifier <param-group-id> \
--username admin --password <alphanumeric-only> \
--organization my-org --bucket my-bucket
```
> **Security best practice — InfluxDB V2 credentials:**
>
> - Generate the initial admin password as a strong random value rather than choosing one by hand, e.g. `aws secretsmanager get-random-password --exclude-punctuation --password-length 32 --query RandomPassword --output text` (InfluxDB requires an alphanumeric password, hence `--exclude-punctuation`).
> - Rotate the initial admin password immediately after first login; it is set during instance creation and should not be used by applications.
> - Create scoped API tokens for each application or service — never share the operator token.
> - The engine does not support automatic token expiration or rotation. Token rotation is the customer's responsibility. There is no automatic synchronization between AWS Secrets Manager and the engine's token management layer.
> - For InfluxDB V3 or new deployments, the preferred approach is Secrets Manager-based Bearer tokens provisioned automatically by the service.
**InfluxDB 2 Read Replica Cluster:**
```bash
aws timestream-influxdb create-db-cluster \
--name my-rr-cluster \
--db-instance-type db.influx.large \
--db-storage-type InfluxIOIncludedT1 \
--allocated-storage 400 \
--deployment-type MULTI_NODE_READ_REPLICAS \
--vpc-subnet-ids subnet-az1 subnet-az2 \
--vpc-security-group-ids sg-abc \
--db-parameter-group-identifier <param-group-id> \
--username admin --password <alphanumeric-only> \
--organization my-org --bucket my-bucket
```
**InfluxDB 3 (cluster):**
```bash
aws timestream-influxdb create-db-cluster \
--name my-v3-cluster \
--db-instance-type db.influx.large \
--db-parameter-group-identifier InfluxDBV3Core \
--vpc-subnet-ids subnet-abc subnet-def \
--vpc-security-group-ids sg-abc
```
> ⚠️ **CRITICAL V3 WARNING:** You **MUST NOT** pass `--username`, `--password`, `--organization`, `--bucket`, or `--deployment-type` when creating V3 clusters. These parameters switch the cluster into a non-V3 initialization mode. V3 clusters use `Bearer` token auth provisioned automatically via Secrets Manager.
**Literal parameter group identifiers:** You can use `InfluxDBV3Core` or `InfluxDBV3Enterprise` as literal identifiers without creating a custom parameter group first. Create a custom group only when you need to override defaults.
### 3. Retrieve Token
**V2:** Token is stored in Secrets Manager at the ARN returned in `influxAuthParametersSecretArn`:
```bash
aws secretsmanager get-secret-value \
--secret-id <influxAuthParametersSecretArn> \
--query SecretString --output text
```
After retrieving the initial credentials, create an all-access operator token via the InfluxDB UI or cookie-based API auth (see V2 Onboarding below).
**V3:** Token secret follows the naming convention `READONLY-InfluxDB-auth-parameters-<CLUSTER_ID>`:
```bash
aws secretsmanager get-secret-value \
--secret-id "READONLY-InfluxDB-auth-parameters-<CLUSTER_ID>" \
--query SecretString --output text
```
The `READONLY-` prefix means the secret is service-managed — modifying it does not change the cluster's actual token.
### 4. Connect
**Security group configuration for publicly accessible instances:**
When creating an instance or cluster with `--publicly-accessible`, the endpoint is exposed over the public internet. Public access is a supported opt-in feature at creation time — by default, instances are private (VPC-only). For publicly accessible deployments, the default security group blocks all inbound traffic. You must add an inbound rule for the InfluxDB port:
```bash
# V2 (port 8086)
aws ec2 authorize-security-group-ingress \
--group-id <sg-id> \
--protocol tcp --port 8086 \
--cidr <your-ip>/32 # or a CIDR range — avoid 0.0.0.0/0 in production
# V3 (port 8181)
aws ec2 authorize-security-group-ingress \
--group-id <sg-id> \
--protocol tcp --port 8181 \
--cidr <your-ip>/32
```
Restrict the CIDR to the smallest set of IPs that need access. Never use `0.0.0.0/0` for production workloads.
**For private (VPC-only) deployments:** Clients must be in the same VPC or reach the instance via VPN, Direct Connect, or Transit Gateway. Security group rules should allow inbound from the VPC CIDR or specific private subnets.
**InfluxDB 2:** Endpoint on port 8086. Use the InfluxDB 2.x API with org/bucket/token.
```
influx config create --config-name my-config \
--host-url https://<endpoint>:8086 \
--org <org> --token <token>
```
**InfluxDB 3:** Endpoint on port 8181. Use SQL or InfluxQL via the InfluxDB 3.x API.
```bash
# Write via line protocol
curl -X POST "https://<endpoint>:8181/api/v3/write_lp?db=<database>" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: text/plain" \
-d "measurement,tag=value field=1.0"
# Query via SQL
curl -X POST "https://<endpoint>:8181/api/v3/query_sql" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"db":"<database>","q":"SELECT * FROM measurement LIMIT 10"}'
```
### 5. Post-Setup
- Configure maintenance window
- Set up CloudWatch alarms → route to `monitoring`
- Design schema → route to `schema-design`
## Private Access via SSM Bastion
For V3 clusters in private subnets without direct connectivity:
```bash
aws ssm start-session --target <bastion-instance-id> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["<CLUSTER_ENDPOINT>"],"portNumber":["8181"],"localPortNumber":["8181"]}'
```
Add `127.0.0.1 <CLUSTER_ENDPOINT>` to `/etc/hosts` so TLS certificate validation succeeds against the forwarded connection.
## Log Delivery to S3
Logs are delivered hourly to S3. The bucket **must** be in the same account and region, with this policy:
> **SSE-KMS note:** SSE-KMS encryption on the log delivery bucket is supported, but the KMS key **must** be owned by the same AWS account as the InfluxDB instance. A cross-account KMS key will break log delivery silently.
```json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "timestream-influxdb.amazonaws.com"},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::BUCKET_NAME/InfluxLogs/*",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "YOUR_ACCOUNT_ID"
},
"ArnLike": {
"aws:SourceArn": "arn:aws:timestream-influxdb:<REGION>:<ACCOUNT_ID>:db-instance/*"
}
}
}]
}
```
Add an `aws:SourceArn` condition to your S3 bucket policy to prevent confused deputy attacks — this ensures requests to the bucket can only originate from your Timestream for InfluxDB instance, not from other AWS services that share the same service principal. This bucket policy applies to your logs bucket (the S3 bucket you configure to receive InfluxDB service logs). The InfluxDB 3 data bucket is provisioned and managed by the service — you do not configure a bucket policy for it directly.
Enable via create or update:
```bash
--log-delivery-configuration '{"s3Configuration":{"bucketName":"BUCKET","enabled":true}}'
```
## Reboot Commands
```bash
# V2 instance
aws timestream-influxdb reboot-db-instance --identifier <instance-id>
# V3 cluster (all nodes)
aws timestream-influxdb reboot-db-cluster --db-cluster-id <cluster-id>
# V3 cluster (specific nodes, up to 3)
aws timestream-influxdb reboot-db-cluster --db-cluster-id <cluster-id> \
--instance-ids <id1> <id2>
```
## Updatable Fields
### InfluxDB 2 (`update-db-instance`)
- `--db-instance-type` — triggers reboot
- `--db-parameter-group-identifier` — triggers reboot
- `--db-storage-type` — triggers reboot
- `--allocated-storage` — increase only
- `--deployment-type` — SINGLE_AZ ↔ WITH_MULTIAZ_STANDBY
- `--port`
- `--log-delivery-configuration`
- `--maintenance-schedule`
### InfluxDB 3 (`update-db-cluster`)
- `--db-instance-type` — triggers reboot
- `--db-parameter-group-identifier` — triggers reboot
- `--port`
- `--failover-mode`
- `--log-delivery-configuration`
- `--maintenance-schedule`
**NOT updatable on V3:** `--allocated-storage` (V3 uses S3), `--deployment-type` (V3 uses param groups for topology), `--db-storage-type`.
## V2 Onboarding: Cookie Auth for Operator Token
After initial provisioning, the credentials in Secrets Manager give you UI access but not a full API operator token. To create one:
1. Sign in to the InfluxDB UI at `https://<endpoint>:8086` with the username/password from Secrets Manager
2. Navigate to **Load Data → API Tokens → Generate API Token → All Access API Token**
3. Copy the generated token — this is your operator token for all API operations
4. Create scoped tokens (read/write per bucket) for application use — avoid using the all-access token in production applications
## Prerequisites for Read Replicas and InfluxDB 3 Enterprise
Both require:
1. **AWS Marketplace subscription** for InfluxData licensed features — subscribe before provisioning
2. **IAM policies** — attach these managed policies to your IAM role/user:
- `AmazonTimestreamInfluxDBFullAccess`
- `AmazonTimestreamConsoleFullAccess`
> **Note:** `AmazonTimestreamInfluxDBFullAccess` is suitable for initial setup and experimentation. For production workloads, replace it with a scoped custom IAM policy that grants only the specific actions your application requires. Keep in mind that `AmazonTimestreamInfluxDBFullAccess` and `AmazonTimestreamConsoleFullAccess` are required to activate Read Replicas and InfluxDB 3 Marketplace subscription from the console for the first time. **After initial setup and first-time activation are complete, replace both `AmazonTimestreamInfluxDBFullAccess` and `AmazonTimestreamConsoleFullAccess` with the scoped custom policy below for all production and operational use.**
Example scoped policy for day-to-day operations (read plus the operational write actions this guide uses — update, reboot, tag):
```json
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"timestream-influxdb:GetDbInstance",
"timestream-influxdb:GetDbCluster",
"timestream-influxdb:ListDbInstances",
"timestream-influxdb:ListDbClusters",
"timestream-influxdb:ListTagsForResource",
"timestream-influxdb:UpdateDbInstance",
"timestream-influxdb:UpdateDbCluster",
"timestream-influxdb:RebootDbInstance",
"timestream-influxdb:RebootDbCluster",
"timestream-influxdb:TagResource"
],
"Resource": [
"arn:aws:timestream-influxdb:<region>:<account-id>:db-instance/*",
"arn:aws:timestream-influxdb:<region>:<account-id>:db-cluster/*"
]
}]
}
```
## Key Differences: V2 vs V3
| Aspect | InfluxDB 2 | InfluxDB 3 |
|--------|-----------|-----------|
| Query language | Flux | SQL, InfluxQL |
| Data model | Orgs → Buckets → Measurements | Databases → Tables |
| Storage | Local disk (TSM engine), allocated at creation | S3-backed (Apache Parquet), no allocated storage parameter |
| Cardinality | Hard limits, performance degrades | Handles high cardinality natively |
| Processing Engine | Not available | Python plugins with triggers |
| Port | 8086 | 8181 |
| AWS resource | `create-db-instance` | `create-db-cluster` |
| Deployment types | SINGLE_AZ, WITH_MULTIAZ_STANDBY | Determined by failover-mode (no deployment-type param) |
| Password | Required at creation | N/A — must not be provided (Bearer token via Secrets Manager) |
| Storage scaling | Yes (update-db-instance) | N/A (S3-backed) |
## Instance Types
| Type | vCPU | Memory | Use Case |
|------|------|--------|----------|
| db.influx.medium | 1 | 8 GiB | Dev/test |
| db.influx.large | 2 | 16 GiB | Small production |
| db.influx.xlarge | 4 | 32 GiB | Medium production |
| db.influx.2xlarge | 8 | 64 GiB | Large production |
| db.influx.4xlarge | 16 | 128 GiB | High-throughput |
| db.influx.8xlarge | 32 | 256 GiB | Enterprise |
| db.influx.12xlarge | 48 | 384 GiB | Enterprise |
| db.influx.16xlarge | 64 | 512 GiB | Enterprise |
| db.influx.24xlarge | 96 | 768 GiB | Enterprise (largest publicly available) |
references/migration/instructions.md
# Migration
## When to Activate
User wants to migrate from LiveAnalytics to InfluxDB 3, from self-managed InfluxDB to managed, or from V2 to V3. Covers data export/import and Parquet conversion.
## Migration Paths
### Path 1: LiveAnalytics → InfluxDB 3 (Certified Migration Plugin)
LiveAnalytics is in maintenance mode. Use the **InfluxData certified LiveAnalytics migration plugin** and its companion migration client. **This plugin is recommended for smaller migrations (under 1 billion records / 125GB).** For larger datasets, contact the account team for guidance.
**How it works:**
1. The migration client runs `UNLOAD` to export LiveAnalytics data to S3 in Parquet format
2. The client generates presigned URLs for the Parquet files
3. The client invokes the migration plugin on the InfluxDB 3 cluster
4. The plugin retrieves S3 objects, transforms to line protocol, and writes to InfluxDB 3
**Data mapping:**
| LiveAnalytics Concept | InfluxDB 3 Concept |
|---|---|
| Table | Measurement |
| Dimensions | Tags |
| Measure name | Tag |
| Measures | Fields |
| Time | Timestamp |
**Steps:**
```bash
# 1. Provision InfluxDB 3 Enterprise cluster (route to getting-started)
# 2. Create S3 bucket for export
aws s3api create-bucket --bucket <bucket> \
--object-lock-enabled-for-bucket --region <region> \
--create-bucket-configuration LocationConstraint=<region>
# 3. Run the migration client (recommended on EC2 t3.medium for auto-rotating IAM creds)
export INFLUXDB3_HOST_URL="https://<process-node-endpoint>:<port>"
export INFLUXDB3_AUTH_TOKEN=$(aws secretsmanager get-secret-value --secret-id "READONLY-InfluxDB-auth-parameters-<CLUSTER_ID>" --query SecretString --output text | python3 -c "import sys,json; print(json.loads(sys.stdin.read())['token'])")
export INFLUXDB3_DATABASE_NAME="<database>"
python3 liveanalytics_influxdb3_migration_client.py \
--live-analytics-database-name <la-database> \
--s3-bucket-name <bucket>
```
**Important constraints:**
- Must run on a single InfluxDB 3 Enterprise **process node** (not the cluster endpoint)
- The cluster should not run ingestion or queries during migration (risk of OOM)
- Recommended for migrations under 1 billion records or 125GB per database
- Throughput: ~30M LiveAnalytics records/hour (varies by data characteristics)
- Run on EC2 to avoid presigned URL expiration issues
- Migration can be resumed if interrupted
**Cost note:** Data migration costs (S3 storage, data transfer) may apply. Discuss with account team for large migrations (5TB+).
### Path 2: Self-Managed InfluxDB → Managed
**From self-managed InfluxDB 2:**
1. Export using `influx backup` or line protocol export
2. Provision managed V2 instance → route to `getting-started`
3. Import using `influx restore` or line protocol write
**From self-managed InfluxDB 3 / InfluxDB Cloud:**
1. Export data via SQL queries to CSV/Parquet
2. Provision managed V3 cluster → route to `getting-started`
3. Bulk import via line protocol or Parquet import
### Path 3: Managed V2 → Managed V3
No in-place upgrade path. Requires data migration:
1. Export from V2 using the InfluxDB 2 API `/api/v2/query` with CSV output
2. Provision V3 cluster → route to `getting-started`
3. Re-design schema for V3 → route to `schema-design` (tags/fields may need restructuring)
4. Ingest via line protocol (compatible across versions)
**Note:** InfluxDB 3 uses SQL and InfluxQL — Flux is not supported. Queries must be rewritten.
## Pre-Migration Checklist
- [ ] Inventory source data volume and time range
- [ ] Map source schema to target schema (route to `schema-design`)
- [ ] Estimate target instance/cluster sizing
- [ ] Ensure Marketplace subscription is active (required for V3 Enterprise)
- [ ] Attach `AmazonTimestreamInfluxDBFullAccess` and `AmazonTimestreamConsoleFullAccess` IAM policies (required for first-time Marketplace/Read Replica activation; replace with a scoped custom policy for production — see getting-started)
- [ ] Test with a subset of data before full migration
- [ ] Plan cutover window and rollback strategy
references/monitoring/instructions.md
# Monitoring & Operations
## When to Activate
User asks about CloudWatch metrics, alarms, instance health, maintenance windows, backups, snapshots, or operational best practices.
## Key CloudWatch Metrics
> **IMPORTANT:** For the full authoritative list of metric names by engine and deployment type, see [metrics.md](metrics.md). The tables below are a quick-reference subset for alarm configuration. Never invent metric names — if it's not in metrics.md, it doesn't exist.
### Instance-Level Metrics (V2 SAZ/MAZ)
| Metric | Description | Alarm Threshold |
|--------|-------------|-----------------|
| `CPUUtilization` | CPU usage percentage | > 80% sustained for 5 min |
| `MemoryUtilization` | Memory usage percentage | > 90% sustained |
| `DiskUtilization` | Disk usage percentage | > 80% |
| `VolumeBytesUsed` | Storage consumed on EBS | > 80% of allocated |
| `ReadIOpsPerSec` / `WriteIOpsPerSec` | I/O operations per second | Baseline + 50% |
| `ReadThroughput` / `WriteThroughput` | Bytes read/written per second | Monitor for anomalies |
### InfluxDB Engine Metrics (V2 SAZ/MAZ CloudWatch only)
| Metric | Description |
|--------|-------------|
| `QueryRequestsTotal` | Query API calls |
| `SeriesCardinality` | Total unique series |
| `HeapMemoryUsage` | Heap memory usage |
| `WriteTimeouts` | Failed write timeouts |
| `APIRequestRate` | Total API request rate |
### V2 Read Replica CloudWatch (LIMITED)
Only these metrics are available: `CPUUtilization`, `MemoryUtilization`, `DiskUtilization`, `ReplicaLag`.
### V3 CloudWatch (LIMITED)
Only these metrics are available: `CPUUtilization`, `MemoryUtilization`. All other V3 metrics require scraping the Prometheus `/metrics` endpoint — see [metrics.md](metrics.md) Part 3B.
## Recommended Alarm Configuration
```bash
# CPU alarm — V2 instance
aws cloudwatch put-metric-alarm \
--alarm-name "InfluxDB-HighCPU-<instance>" \
--metric-name CPUUtilization \
--namespace AWS/TimestreamInfluxDB \
--statistic Average --period 300 --threshold 80 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 3 \
--dimensions Name=DBInstanceIdentifier,Value=<instance-id> \
--alarm-actions <sns-topic-arn>
# CPU alarm — V3 cluster (use DBClusterIdentifier dimension)
aws cloudwatch put-metric-alarm \
--alarm-name "InfluxDB-HighCPU-<cluster>" \
--metric-name CPUUtilization \
--namespace AWS/TimestreamInfluxDB \
--statistic Average --period 300 --threshold 80 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 3 \
--dimensions Name=DBClusterIdentifier,Value=<cluster-id> \
--alarm-actions <sns-topic-arn>
# Storage alarm — V2 instance ONLY (VolumeBytesUsed is NOT available for V3)
aws cloudwatch put-metric-alarm \
--alarm-name "InfluxDB-StorageHigh-<instance>" \
--metric-name VolumeBytesUsed \
--namespace AWS/TimestreamInfluxDB \
--statistic Maximum --period 300 \
--threshold <80-percent-of-allocated-bytes> \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1 \
--dimensions Name=DBInstanceIdentifier,Value=<instance-id> \
--alarm-actions <sns-topic-arn>
```
> **V3 storage monitoring:** V3 uses S3-backed storage — there is no `VolumeBytesUsed` metric. Monitor storage costs via AWS Cost Explorer or query `system.parquet_files` for actual data size.
>
> **MUST:** Enable SSE-KMS on your SNS topic to encrypt alarm notifications at rest — never use at-rest unencrypted notifications for operational data. Alarm notifications can contain operationally sensitive information (instance IDs, metric thresholds, account details). Ensure your SNS topic access policy restricts `sns:Subscribe` to authorized principals only, and verify that all subscription endpoints (email, HTTPS, Lambda) belong to your organization. If alarm notifications are also delivered to CloudWatch Logs, enable SSE-KMS encryption on those log groups as well.
## Maintenance Windows
Customer Managed Maintenance Windows:
- Set preferred day, time, and timezone via console, CLI, or SDK
- Engine patches and minor updates applied during the window
- Major version changes require explicit approval
```bash
# V2 instance
aws timestream-influxdb update-db-instance \
--identifier <instance-id> \
--maintenance-schedule '{"timezone":"UTC","preferredMaintenanceWindow":"Sun:03:00-Sun:05:00"}'
# V3 cluster
aws timestream-influxdb update-db-cluster \
--db-cluster-id <cluster-id> \
--maintenance-schedule '{"timezone":"UTC","preferredMaintenanceWindow":"Sun:03:00-Sun:05:00"}'
```
## Backup & Snapshots
- **Service-managed snapshots** are taken automatically: every hour for InfluxDB 2 (retained 24 hours) and every hour for InfluxDB 3 (retained 30 days). These are NOT directly accessible to customers — there is no console or CLI to list, browse, or restore them.
- **To recover from a snapshot**, customers must open a **Sev-2 support ticket** requesting recovery or retention of a specific snapshot. There is no self-service restore path.
- **Customer-managed snapshots are not available** — there is no `create-db-snapshot` CLI command or equivalent. Do NOT tell customers they can create, schedule, or manage their own snapshots.
- For self-managed backups, use the InfluxDB data-plane API to export data via line protocol or SQL queries to S3:
```bash
# V2: Export data via influx CLI
influx backup /path/to/backup --host https://<endpoint>:8086 --token <token>
# V3: Export data via SQL query to CSV
curl -X POST "https://<endpoint>:8181/api/v3/query_sql" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"db":"<database>","q":"SELECT * FROM <table>","format":"csv"}' > backup.csv
```
## AWS CloudTrail Integration
Timestream for InfluxDB is integrated with AWS CloudTrail and logs all control-plane API calls (e.g., `CreateDbInstance`, `DeleteDbInstance`, `UpdateDbInstance`, `CreateDbCluster`). Enable CloudTrail in your account to maintain an audit trail of who made changes, when, and from where.
**Important limitation:** Timestream for InfluxDB supports **control-plane CloudTrail events only**. Data-plane operations (reads/writes to InfluxDB via the HTTP API) are not logged via CloudTrail — use InfluxDB's own audit logging or the `/metrics` endpoint for data access observability.
## Operational Checklist
- [ ] CloudWatch alarms configured for CPU, memory, storage, and I/O
- [ ] Maintenance window set to low-traffic period
- [ ] Data export/backup strategy defined (service snapshots are not self-service — use data-plane export for customer-controlled backups)
- [ ] SNS topic configured for alarm notifications
- [ ] Instance right-sized for workload (check CPU/memory utilization trends)
- [ ] Storage monitoring in place (V2: allocated storage usage; V3: S3 costs)
references/monitoring/metrics.md
# Monitoring Metrics for Amazon Timestream for InfluxDB
## CRITICAL RULE: NEVER INVENT METRIC NAMES
Only use metric names from the authoritative tables below.
If you are unsure whether a metric exists, say so explicitly.
Do NOT paraphrase, abbreviate, or PascalCase a metric name unless the
authoritative table shows it in that form.
---
## PART 1 — UNDERSTAND THE COVERAGE GAP FIRST
Before recommending any metric, determine:
1. Which engine? InfluxDB 2 (TSM) or InfluxDB 3 (Parquet/Arrow)?
2. Which deployment mode? SAZ, MAZ, Read Replica (v2 only)?
3. Which monitoring path? CloudWatch (managed, no scraping) or
Prometheus /metrics endpoint (self-managed scraping)?
The coverage differs significantly:
| Deployment | CloudWatch coverage | /metrics endpoint coverage |
|-----------------------|---------------------------|---------------------------|
| InfluxDB 2 SAZ / MAZ | RICH (see Part 2A) | RICH (see Part 2B) |
| InfluxDB 2 Read Replica | LIMITED: CPUUtilization, MemoryUtilization, DiskUtilization, ReplicaLag only | RICH (same as SAZ/MAZ) |
| InfluxDB 3 (all) | LIMITED: CPUUtilization, MemoryUtilization only | RICH (see Part 3B) |
If the customer needs metrics not available in CloudWatch for their
deployment, tell them: "That metric is not available in CloudWatch for
this deployment type. Use the Prometheus /metrics endpoint instead."
---
## PART 2A — InfluxDB 2: CloudWatch Metric Names (AUTHORITATIVE)
Use these EXACT names when discussing CloudWatch. Format: CloudWatchName.
### Compute & Storage
- CPUUtilization
- MemoryUtilization
- DiskUtilization
- VolumeBytesUsed ← storage consumed on EBS, NOT InfluxDB data size
- ReadIOpsPerSec, WriteIOpsPerSec, TotalIOpsPerSec
- ReadThroughput, WriteThroughput
### InfluxDB Engine (published to customer CloudWatch namespace)
- EngineUptime
- TotalBuckets
- WriteTimeouts
- ActiveTaskWorkers
- TaskExecutionFailures
- ActiveMemoryAllocation
- HeapMemoryUsage
- QueryRequestsTotal
- SeriesCardinality
- APIRequestRate
- QueryResponseVolume
### Read Replica only
- ReplicaLag ← only available on Read Replica deployments
WRONG names (do NOT use): WriteRequestsTotal, QueryLatency,
StorageUtilization, influxdb_write_requests, ReadLatency, WriteLatency.
---
## PART 2B — InfluxDB 2: Prometheus /metrics Endpoint Names (AUTHORITATIVE)
Use these EXACT names when discussing the /metrics scrape endpoint.
These are Prometheus-format names (snake_case, with_total/_seconds/_bytes suffixes).
| Concern | Metric name |
|----------------------|--------------------------------------------------|
| Uptime | influxdb_uptime_seconds |
| Bucket count | influxdb_buckets_total |
| Write timeouts | storage_writer_timeouts |
| Task workers active | task_executor_total_runs_active |
| Task failures | task_scheduler_total_execute_failure |
| Memory (alloc) | go_memstats_alloc_bytes |
| Memory (heap) | go_memstats_heap_alloc_bytes |
| Query count | qc_requests_total |
| Query exec duration | qc_executing_duration_seconds (histogram) |
| Query all duration | qc_all_duration_seconds (histogram) |
| Series cardinality | storage_bucket_series_num |
| HTTP request rate | http_api_requests_total |
| Query response bytes | http_query_response_bytes |
| Query read duration | query_influxdb_source_read_request_duration_seconds (histogram) |
WRONG names (do NOT use): influxdb_write_requests, ReadLatency,
WriteLatency, QueryLatency, StorageUtilization, WriteRequestsTotal.
---
## PART 3A — InfluxDB 3: CloudWatch Metric Names (AUTHORITATIVE)
CloudWatch coverage for InfluxDB 3 is LIMITED to:
- CPUUtilization
- MemoryUtilization
All other monitoring for InfluxDB 3 must use the /metrics endpoint.
Do NOT tell a customer to find write throughput, query latency, or
cardinality in CloudWatch for InfluxDB 3 — those are not there.
---
## PART 3B — InfluxDB 3: Prometheus /metrics Endpoint Names (AUTHORITATIVE)
### Tier 1 — Critical (always check these first)
| Concern | Metric name |
|----------------------------|----------------------------------------------------|
| Write throughput (lines) | influxdb3_write_lines_total |
| Write throughput (bytes) | influxdb3_write_bytes_total |
| Rejected writes | influxdb3_write_lines_rejected_total |
| Query OOM errors | query_datafusion_query_execution_ooms_total |
| DataFusion memory pool | datafusion_mem_pool_bytes |
| HTTP request count | http_requests_total |
| HTTP request latency | http_request_duration_seconds (histogram) |
| Query execution duration | influxdb_iox_query_log_execute_duration_seconds |
| Query max memory | influxdb_iox_query_log_max_memory |
### Tier 2 — Performance Optimization
| Concern | Metric name |
|----------------------------|----------------------------------------------------|
| Parquet cache size | influxdb3_parquet_cache_size_bytes |
| Parquet cache accesses | influxdb3_parquet_cache_access_total |
| Object store op duration | object_store_op_duration_seconds |
| Object store bytes | object_store_transfer_bytes_total |
| Replication lag (MAZ only) | influxdb3_replica_ttbr_duration_seconds |
### Tier 3 — Stability & Health
| Concern | Metric name |
|----------------------------|----------------------------------------------------|
| Thread panics | thread_panic_count_total |
| Catalog retries | influxdb3_catalog_operation_retries_total |
| Allocator memory | jemalloc_memstats_bytes |
| gRPC duration (multi-node) | grpc_request_duration_seconds |
### InfluxDB 3 WAL / Ingest detail metrics (from /metrics)
influxdb3_wal_flush_latency_seconds, influxdb3_wal_bytes_flushed_total,
influxdb3_wal_rows_flushed_total, influxdb3_wal_flush_total,
influxdb3_snapshot_bytes_written_total, influxdb3_snapshot_total
### Important distinctions for InfluxDB 3 /metrics
- influxdb3_write_bytes_total = cumulative RAW BYTES WRITTEN, NOT database
size on disk
- object_store_transfer_bytes_total = cumulative object store I/O
(reads + writes combined), NOT current storage used
- For ACTUAL storage size: query the system table → SELECT * FROM
system.parquet_files
---
## PART 4 — HOW TO GUIDE A CUSTOMER: DECISION TREE
### Path A — Customer wants CloudWatch monitoring (no scraping)
Step 1: Confirm engine and deployment type (v2 SAZ/MAZ, v2 Read Replica,
v3).
Step 2: Tell them which metrics ARE available in CloudWatch for that type
(use tables in Part 2A or 3A above).
Step 3: For metrics NOT in CloudWatch, tell them explicitly: "This metric
is not published to CloudWatch for [deployment type]. You will
need to scrape the /metrics endpoint to get it."
Step 4: For CloudWatch alerting/scaling, direct them to:
https://docs.aws.amazon.com/timestream/latest/developerguide/timestream-influxdb-cloudwatch.html
Step 5: ⚠️ WARN about CloudWatch custom metric cost. A misconfigured
Telegraf sending raw data (not just /metrics) as CloudWatch
custom metrics can cause unexpectedly high bills.
Always verify Telegraf is scraping only the /metrics endpoint,
not forwarding raw write traffic.
### Path B — Customer wants to scrape the /metrics endpoint
Step 1: The endpoint is available at: http://`<instance-endpoint>`:8086/metrics
(InfluxDB 2) or the configured HTTP port (InfluxDB 3).
Step 2: Authentication: pass the operator/admin token as a Bearer token
in the Authorization header.
Step 3: Use a Prometheus scraper or Telegraf with inputs.prometheus
plugin pointing to the /metrics URL.
Step 4: Use ONLY the metric names from Part 2B (v2) or Part 3B (v3).
Step 5: To store scraped metrics back into InfluxDB or forward to
CloudWatch, use outputs.influxdb_v2 or outputs.cloudwatch in
Telegraf — but verify output configuration carefully (see Step 5
in Path A warning above).
Step 6: For InfluxDB 3 storage size specifically, use the SQL system
table query instead of a /metrics metric:
SELECT * FROM system.parquet_files
references/processing-engine/instructions.md
# Processing Engine
## When to Activate
User asks about data processing plugins, triggers, downsampling, data transformation, alerting, or the Processing Engine feature of InfluxDB 3.
**Prerequisite:** Processing Engine is InfluxDB 3 only. If the user is on V2, inform them and offer to route to `migration`.
## Overview
The Processing Engine is an embedded Python virtual machine inside InfluxDB 3 that extends database functionality with plugins. **Only InfluxData certified plugins are supported** — custom user-written plugins are not supported.
## Available Certified Plugins
| Plugin | Trigger Type | Use Case |
|--------|-------------|----------|
| **Downsampler** | Scheduled, HTTP | Aggregate high-frequency data into lower-resolution summaries |
| **Basic Transformation** | Scheduled, Data write | Field name normalization, unit conversions, data cleaning |
| **MAD Anomaly Detection** | Data write | Real-time outlier detection using Median Absolute Deviation |
| **State Change Monitor** | Scheduled, Data write | Track field value changes, alert on state transitions |
| **System Metrics Collector** | Scheduled | Collect CPU, memory, disk, network metrics from the host |
| **LiveAnalytics Migration** | HTTP | Migrate data from Timestream for LiveAnalytics (smaller migrations under 1B records) |
Source code and documentation: [InfluxData Plugins Repository](https://github.com/influxdata/influxdb3_plugins/tree/main/influxdata)
## Trigger Types
| Trigger | Specification | When It Fires |
|---------|--------------|---------------|
| Data write | `table:<name>` or `all_tables` | When data is written to tables |
| Scheduled | `every:<interval>` or `cron:<expression>` | At specified intervals |
| HTTP request | `request:<endpoint>` | When HTTP requests hit the plugin endpoint |
## Creating Triggers
```bash
# Downsampler — aggregate CPU metrics hourly
influxdb3 create trigger \
--database metrics \
--plugin-filename "downsampler/downsampler.py" \
--trigger-spec "every:1h" \
--trigger-arguments 'source_measurement=cpu_detailed,target_measurement=cpu_hourly,interval=1h,window=6h,calculations="usage:avg.max_usage:max"' \
cpu_downsampler
# MAD Anomaly Detection — real-time outlier detection on sensor data
# Fetch the Slack webhook from Secrets Manager — never hardcode secrets in trigger arguments
SLACK_WEBHOOK=$(aws secretsmanager get-secret-value --secret-id influxdb3/slack-webhook --query SecretString --output text)
influxdb3 create trigger \
--database sensors \
--plugin-filename "mad_check/mad_check_plugin.py" \
--trigger-spec "all_tables" \
--trigger-arguments "measurement=temperature_sensors,mad_thresholds=\"temp:2.5:20:5\",senders=slack,slack_webhook_url=\"$SLACK_WEBHOOK\"" \
temp_anomaly_detector
# Basic transformation — clean field names on incoming data
influxdb3 create trigger \
--database iot \
--plugin-filename "basic_transformation/basic_transformation.py" \
--trigger-spec "all_tables" \
--trigger-arguments 'measurement=raw_sensors,target_measurement=clean_sensors,names_transformations=.*:"snake alnum_underscore_only"' \
sensor_cleaner
# State Change Monitor — alert on equipment status changes
influxdb3 create trigger \
--database factory \
--plugin-filename "state_change/state_change_check_plugin.py" \
--trigger-spec "every:5m" \
--trigger-arguments 'measurement=equipment,field_change_count="status:3",window=15m,senders=slack' \
equipment_monitor
# System Metrics Collector — collect host metrics every 30s
influxdb3 create trigger \
--database monitoring \
--plugin-filename "system_metrics/system_metrics.py" \
--trigger-spec "every:30s" \
--trigger-arguments 'hostname=db-server-01,include_cpu=true,include_memory=true,include_disk=true,include_network=true' \
system_monitor
```
## Managing Triggers
```bash
# List triggers
influxdb3 show system summary --database <db> --token <token>
# Disable a trigger
influxdb3 disable trigger --database <db> --trigger-name <name>
# Delete a trigger
influxdb3 delete trigger --database <db> --trigger-name <name>
```
## Configuration Options
**Trigger arguments:** Pass key=value pairs to configure plugin behavior:
```bash
--trigger-arguments 'threshold=90,notify_email=admin@example.com'
```
**Secrets in plugin arguments:** Do not hardcode webhook URLs, API keys, or other credentials directly in scripts or source control. Store them in AWS Secrets Manager and retrieve them at trigger-creation time (e.g., `aws secretsmanager get-secret-value` into an environment variable, as shown in the MAD anomaly-detection example above). **Limitation:** the resolved value is still written into the trigger spec and is visible in plaintext in `system.processing_engine_triggers` — this approach keeps secrets out of source control but does not protect them at rest inside InfluxDB. Restrict access to the database/system tables accordingly, and rotate any secret that is exposed this way.
**Error handling:** `--error-behavior log` (default), `retry`, or `disable`
**Async execution:** `--run-asynchronous` for heavy processing tasks
**TOML config files:** For complex configurations, use `--trigger-arguments "config_file_path=config.toml"`
## Multi-Node Deployment
| Plugin Type | Run On | Reason |
|-------------|--------|--------|
| Data write plugins | Ingester nodes | Process data at ingestion point |
| HTTP request plugins | Querier nodes | Handle API traffic |
| Scheduled plugins | Any configured node | Pin to single node to avoid duplicates |
## Monitoring Plugin Execution
```sql
-- View plugin logs
SELECT * FROM system.processing_engine_logs
WHERE trigger_name = 'your_trigger_name'
AND time > now() - INTERVAL '1 hour'
ORDER BY event_time DESC;
-- Check trigger status
SELECT * FROM system.processing_engine_triggers
WHERE database = 'your_database';
```
## Troubleshooting
| Issue | Fix |
|-------|-----|
| Plugin not triggering | Verify trigger is enabled via `influxdb3 show system summary`. Check trigger spec syntax |
| High memory usage | Reduce window sizes, adjust batch processing intervals |
| Duplicate processing on multi-node | Pin scheduled triggers to a single node |
| Too many alerts | Increase trigger counts/thresholds, add debounce duration |
## What's NOT Supported
- **Custom user-written plugins** — only InfluxData certified plugins are available. Custom user-written plugins are not supported.
- **Custom Python package installation** — plugins run with the packages bundled in the certified plugin set
- **Arbitrary filesystem or network access** — plugins operate within a constrained sandbox
references/schema-design/instructions.md
# Schema & Data Modeling
## When to Activate
User asks about tag vs field decisions, cardinality management, table/measurement design, retention policies, or InfluxDB 3 best practices for data modeling.
## Workflow
### 1. Identify the Engine
Schema design differs significantly between V2 and V3. Confirm the engine before advising.
### 2. Core Concepts
**Line protocol** (both engines):
```
measurement,tag1=val1,tag2=val2 field1=1.0,field2="text" timestamp
```
**Tags** = indexed, low-cardinality metadata (device_id, region, sensor_type)
**Fields** = values not indexed by default (temperature, cpu_usage, response_time)
**Timestamp** = nanosecond precision, always present
### 3. Tag vs Field Decision
Ask: "Will I filter or GROUP BY this column frequently?"
- **Yes** → Tag (indexed, fast lookups)
- **No** → Field (not indexed by default, stores the actual measurements)
**Cardinality rule:** The product of all unique tag value combinations = series cardinality.
- V2: Keep below 1M series per bucket. Performance degrades sharply above this.
- V3: No hard limit. High cardinality is handled natively, but tag design still affects query performance and storage efficiency.
### 4. InfluxDB 3 Schema Best Practices
**Table and column limits:**
- `maxTables` default: **4,000** per database. Recommended: keep under ~500 for optimal query performance.
- `maxColumnsPerTable` default: **200**. Each unique tag key or field key counts as a column.
- Both are configurable via parameter groups. Exceeding these limits will reject writes.
**Table design:**
- One table per logical measurement type (e.g., `cpu`, `memory`, `http_requests`)
- Avoid mega-tables with hundreds of fields — split by domain
- Use meaningful table names (they map to SQL table names)
**Partition templates:**
- Default: partition by day. Good for most workloads.
- High-volume: partition by hour if writing >1M points/day per table
- Configure via: `--partition-template tag:region,tag:host,time:%Y-%m-%d`
**Deduplication and uniqueness:**
- InfluxDB 3 deduplicates on: all tags + timestamp (the "primary key")
- Two points with identical tags and timestamp → last write wins
- To preserve both: add a distinguishing tag or use different timestamps
**Field indexing (V3):**
- Fields are NOT indexed by default
- For fields used in WHERE clauses, create a field index:
```sql
CREATE INDEX idx_status ON http_requests (status);
```
**Retention:**
- V2: Set retention policy per bucket
- V3: Set retention period per database
### 5. Common Anti-Patterns
| Anti-Pattern | Problem | Fix |
|-------------|---------|-----|
| Encoding data in tag values (e.g., `sensor_123_temp`) | Explodes cardinality | Split into `sensor_id=123` tag + `temp` field |
| Using high-cardinality values as tags (UUIDs, timestamps) | V2: crashes. V3: bloated indexes | Move to fields; use field indexes if needed |
| Single mega-table for all data | Poor query performance, hard to manage | Split by measurement domain |
| Missing timestamp precision | Accidental deduplication | Use nanosecond precision for high-frequency data |
| Storing constants as fields | Wastes storage on every point | Move to tags (indexed once per series) |
### Canonical tag examples for HTTP / API logs
For typical HTTP request log schemas, use these as default **tags** (low-to-moderate cardinality, commonly filtered/grouped):
- `method` (~10 values: GET, POST, etc.)
- `status_code` (~20 values: 200, 404, 500, etc.)
- `endpoint` (the request path — typically <500 unique paths in a well-normalized API; commonly filtered/grouped in error queries)
Note on `endpoint` cardinality: if the application logs raw paths with embedded IDs (e.g., `/users/123` instead of `/users/:id`), normalize the path before ingestion. The default classification is **tag**.
### Canonical field examples
- `response_time_ms`, `bytes_sent` (numeric measurements)
- `user_agent`, `request_id` (unbounded cardinality — never tags)
### 6. Example Schemas
**IoT sensor data:**
```
sensors,device_id=d001,location=factory-a,type=temperature value=23.5 1714000000000000000
sensors,device_id=d001,location=factory-a,type=humidity value=45.2 1714000000000000000
```
**Application metrics:**
```
http_requests,method=GET,endpoint=/api/users,status=200 response_time=45.2,bytes=1024 1714000000000000000
```
**Infrastructure monitoring:**
```
cpu,host=web-01,region=us-east-1 usage_user=23.5,usage_system=5.2,usage_idle=71.3 1714000000000000000
```
references/troubleshooting/instructions.md
# Troubleshooting
## When to Activate
User reports errors, connection failures, query problems, write failures, performance issues, or unexpected behavior with Timestream for InfluxDB.
## Diagnostic Workflow
1. **Identify the engine** — V2, V2 Read Replica, or V3. Error formats and APIs differ.
2. **Classify the error** — Connection, write, query, or operational.
3. **Check the error table below** for known issues and fixes.
4. **If not found**, check CloudWatch metrics (route to `monitoring`) and instance status.
## Connection Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `connection refused` on port 8086/8181 | Security group missing inbound rule | Add inbound rule for port 8086 (V2) or 8181 (V3) from client CIDR. For publicly accessible instances, the default SG blocks all inbound — you must explicitly allow traffic. For private instances, client must be in the same VPC or connected network |
| `TLS handshake failure` | Certificate mismatch or expired | Use the endpoint's TLS certificate; verify system CA bundle is current |
| `connection timeout` | Instance in different VPC or subnet | Verify VPC peering, route tables, and NACLs. Private instances are not reachable from the public internet |
| `401 Unauthorized` | Invalid or expired API token | Regenerate token via console or API. V2: org-scoped tokens. V3: database-scoped tokens |
| `connection reset by peer` | Instance restarting (maintenance) | Retry with backoff. Check if maintenance window is active |
## Write Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `413 Request Entity Too Large` | Batch exceeds max payload size | Reduce batch size. V2: 50MB max. V3: check current limits |
| `429 Too Many Requests` | Write rate limit exceeded | Implement exponential backoff. Consider larger instance type |
| `partial write: field type conflict` (V2) | Field type changed (int → float) | Field types are immutable per measurement in V2. Drop and recreate, or use a new field name |
| `write timeout` | Instance under heavy load or undersized | Check CPU/memory metrics. Scale up instance type or reduce write batch size |
## Query Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `500 Internal Server Error: datafusion error` (V3) | Query engine error, often with Parquet files | Check for corrupted Parquet segments. File a support ticket with the full error |
| `Execution error for 'deduplicate batches'` (V3) | Parquet object not found during deduplication | Known issue under high load. Retry the query. If persistent, contact support |
| `query timeout` | Query scanning too much data | Add time range filters. Use `LIMIT`. Check if indexes exist for filter columns |
| `memory allocation limit exceeded` (V2) | Flux query consuming too much memory | Add `\|> limit()` earlier in the pipeline. Reduce time range. Use `\|> aggregateWindow()` to downsample |
| `bucket not found` (V2) / `database not found` (V3) | Wrong bucket/database name or wrong API version | Verify the name. Ensure you're using the correct API (V2 API for V2, V3 API for V3) |
## Performance Issues
| Symptom | Likely Cause | Investigation |
|---------|-------------|---------------|
| Slow queries | Missing indexes, full table scans | V3: Check `EXPLAIN` output. Add field indexes for WHERE clause columns |
| High write latency | Instance undersized or disk I/O saturated | Check `WriteIOpsPerSec`, `WriteThroughput`, and `DiskUtilization` in CloudWatch (V2) or scrape `/metrics` (V3) |
| Increasing disk usage | No retention policy or retention too long | V2: Check bucket retention. V3: Check database retention period |
| Storage full on Read Replica Cluster | Storage cannot be scaled on RR clusters | Read Replica Clusters do not support storage scaling. Must create a new cluster with larger storage and migrate. V2 SAZ/MAZ instances do support scaling. |
| High CPU sustained | Compaction backlog or heavy query load | Check `qc_requests_total` and `qc_executing_duration_seconds` (V2 /metrics). Consider read replicas for query offloading |
| Replication lag (Read Replicas) | Write volume exceeding replication throughput | Monitor `ReplicaLag` metric. Scale up instance type |
## InfluxDB 3 Specific Issues
**S3 VPC Endpoint (V3 private subnets):**
- V3 requires an S3 VPC Gateway Endpoint in the same account VPC for private deployments
- See `references/troubleshooting/s3-vpc-endpoint.md` for details and fix
- Use `scripts/check_vpc_endpoints.sh` to verify
**Deduplication errors:**
- InfluxDB 3 deduplicates on all tags + timestamp
- If you see unexpected data loss, check if two writes have identical tag sets and timestamps
- Add a distinguishing tag or use nanosecond-precision timestamps
**Parquet errors under load:**
- `Object at location ... not found` during queries indicates a compaction race condition
- Retry the query. If persistent across multiple queries, file a support ticket
- Include: cluster ID, region, time of error, full error message, query that triggered it
**Processing Engine plugin failures:**
- Check plugin logs via the InfluxDB 3 API
- Common: Python dependency not available in the sandboxed environment
- Route to `processing-engine` for plugin-specific troubleshooting
## Escalation Path
If the issue cannot be resolved with the above:
1. Gather: instance/cluster ID, region, timestamps of errors, full error messages, CloudWatch metrics screenshots
2. Open an AWS Support case under Timestream for InfluxDB
3. For critical production issues, request Sev-2 with business impact description
references/troubleshooting/s3-vpc-endpoint.md
# S3 VPC Endpoint Requirement (InfluxDB 3)
## Problem
InfluxDB 3 uses Amazon S3 for WAL and data storage (Parquet files). If your V3 instance or cluster is in a **private subnet** without internet access, it requires an S3 VPC Gateway Endpoint to function.
## Symptoms
- Instance fails to start or becomes unhealthy after provisioning
- "S3 endpoint does not exist" errors in logs
- Write failures with no clear error message
## Fix
Create an S3 VPC Gateway Endpoint in the **same VPC and account** as the InfluxDB 3 instance:
```bash
aws ec2 create-vpc-endpoint \
--vpc-id <vpc-id> \
--service-name com.amazonaws.<region>.s3 \
--route-table-ids <route-table-id> \
--vpc-endpoint-type Gateway
```
## Important Notes
- The S3 endpoint **must be in the same account VPC** — shared subnets from another account will NOT work
- This applies to V3 only (V2 does not use S3 for storage)
- Verify with: `aws ec2 describe-vpc-endpoints --filters Name=vpc-id,Values=<vpc-id>`
- Use `scripts/check_vpc_endpoints.sh` to automate this check
scripts/check_vpc_endpoints.sh
#!/usr/bin/env bash
# Check if S3 VPC Gateway Endpoint exists for InfluxDB 3 private deployments.
# Usage: ./check_vpc_endpoints.sh <vpc-id> <region>
set -euo pipefail
VPC_ID="${1:?Usage: check_vpc_endpoints.sh <vpc-id> <region>}"
REGION="${2:?Usage: check_vpc_endpoints.sh <vpc-id> <region>}"
echo "Checking S3 VPC endpoints for ${VPC_ID} in ${REGION}..."
ENDPOINTS=$(aws ec2 describe-vpc-endpoints \
--region "$REGION" \
--filters "Name=vpc-id,Values=${VPC_ID}" "Name=service-name,Values=com.amazonaws.${REGION}.s3" \
--query 'VpcEndpoints[*].{Id:VpcEndpointId,State:State,Type:VpcEndpointType,RouteTableIds:RouteTableIds}' \
--output json 2>/dev/null) || { echo "ERROR: Failed to query VPC endpoints. Check AWS credentials and region."; exit 1; }
COUNT=$(echo "$ENDPOINTS" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))")
if [ "$COUNT" -eq 0 ]; then
echo ""
echo "❌ NO S3 VPC endpoint found for ${VPC_ID}"
echo ""
echo "InfluxDB 3 requires an S3 Gateway Endpoint in private subnets."
echo "Create one with:"
echo ""
echo " aws ec2 create-vpc-endpoint \\"
echo " --vpc-id ${VPC_ID} \\"
echo " --service-name com.amazonaws.${REGION}.s3 \\"
echo " --route-table-ids <your-route-table-id> \\"
echo " --vpc-endpoint-type Gateway \\"
echo " --region ${REGION}"
echo ""
echo "Note: The endpoint must be in the SAME account VPC (shared subnets won't work)."
exit 1
else
echo ""
echo "✅ Found ${COUNT} S3 VPC endpoint(s):"
echo "$ENDPOINTS" | python3 -c "
import sys, json
for ep in json.load(sys.stdin):
print(f\" {ep['Id']} — State: {ep['State']}, Type: {ep['Type']}\")
if ep.get('RouteTableIds'):
print(f\" Route tables: {', '.join(ep['RouteTableIds'])}\")
"
exit 0
fi
scripts/get_token.sh
#!/usr/bin/env bash
# Retrieve InfluxDB auth token from AWS Secrets Manager.
# After provisioning, the admin token is stored in the secret referenced by influxAuthParametersSecretArn.
# Usage: ./get_token.sh <secret-arn-or-name> <region>
#
# WARNING: The token is a sensitive credential. This script writes it to a
# restricted file (~/.influxdb_token) rather than printing it to stdout to
# avoid exposure in shell history, terminal logs, or CI/CD output.
set -euo pipefail
SECRET="${1:?Usage: get_token.sh <secret-arn-or-name> <region>}"
REGION="${2:?Usage: get_token.sh <secret-arn-or-name> <region>}"
TOKEN_FILE="${3:-${HOME}/.influxdb_token}"
echo "Retrieving token from Secrets Manager..."
SECRET_VALUE=$(aws secretsmanager get-secret-value \
--secret-id "$SECRET" \
--region "$REGION" \
--query 'SecretString' \
--output text 2>/dev/null) || { echo "ERROR: Failed to retrieve secret. Check ARN and permissions."; exit 1; }
# Parse the token from the JSON secret
TOKEN=$(echo "$SECRET_VALUE" | python3 -c "
import sys, json
raw = sys.stdin.read().strip()
try:
data = json.loads(raw)
for key in ['token', 'influxdb_token', 'admin_token', 'api_token']:
if key in data:
print(data[key])
sys.exit(0)
print('Available keys: ' + ', '.join(data.keys()), file=sys.stderr)
sys.exit(1)
except json.JSONDecodeError:
print(raw)
") || { echo "ERROR: Could not parse token from secret. Check secret format — any 'Available keys' line above shows what was found."; exit 1; }
# Write token to a restricted file (umask ensures 600 from creation, no race window)
(umask 077; echo "$TOKEN" > "$TOKEN_FILE")
chmod 600 "$TOKEN_FILE" # defense-in-depth
echo "Token retrieved successfully and written to: $TOKEN_FILE (mode 600)"
echo ""
echo "To use:"
echo " export INFLUXDB_TOKEN=\$(cat $TOKEN_FILE)"
echo ""
echo "WARNING: The token is a secret. Do not log, commit, or share this value."
scripts/health_check.sh
#!/usr/bin/env bash
# Health check for Timestream for InfluxDB instances/clusters.
# Usage: ./health_check.sh <endpoint> <port> [token] [database] [--insecure]
#
# TLS verification is enabled by default. Use --insecure only for local
# port-forwarding scenarios where the certificate doesn't match localhost.
set -euo pipefail
# Separate the --insecure flag from positional args before assignment, so a
# trailing --insecure is never mistaken for the token/database positional.
INSECURE=false
POSITIONAL=()
for arg in "$@"; do
if [ "$arg" = "--insecure" ]; then
INSECURE=true
else
POSITIONAL+=("$arg")
fi
done
ENDPOINT="${POSITIONAL[0]:?Usage: health_check.sh <endpoint> <port> [token] [database] [--insecure]}"
PORT="${POSITIONAL[1]:?Usage: health_check.sh <endpoint> <port> [token] [database] [--insecure]}"
# Validate inputs before building the URL
if ! echo "$ENDPOINT" | grep -qE '^[a-zA-Z0-9.-]+$'; then
echo "ERROR: Invalid endpoint format (expected a hostname: letters, digits, '.', '-')" >&2
exit 1
fi
if ! [[ "$PORT" =~ ^[0-9]{1,5}$ ]] || [ "$PORT" -lt 1 ] || [ "$PORT" -gt 65535 ]; then
echo "ERROR: Invalid port (must be 1-65535)" >&2
exit 1
fi
# Token: prefer env var or file over positional arg (avoids exposure in ps/history)
TOKEN="${POSITIONAL[2]:-${INFLUXDB_TOKEN:-}}"
if [ -z "$TOKEN" ] && [ -f "${HOME}/.influxdb_token" ]; then
TOKEN=$(cat "${HOME}/.influxdb_token")
fi
DB="${POSITIONAL[3]:-}"
CURL_TLS_OPTS=""
if $INSECURE; then
CURL_TLS_OPTS="-k"
echo "WARNING: TLS certificate verification disabled (--insecure). Do not use in production."
fi
BASE="https://${ENDPOINT}:${PORT}"
echo "Checking ${BASE}..."
# Ping (no auth required)
echo -n " /ping: "
HTTP_CODE=$(curl -s $CURL_TLS_OPTS -o /dev/null -w "%{http_code}" "${BASE}/ping" 2>/dev/null) || HTTP_CODE="FAIL"
if [ "$HTTP_CODE" = "204" ] || [ "$HTTP_CODE" = "200" ]; then
echo "OK ($HTTP_CODE)"
else
echo "FAILED ($HTTP_CODE)"
fi
# Health (no auth required on most versions)
echo -n " /health: "
RESP=$(curl -s $CURL_TLS_OPTS -w "\n%{http_code}" "${BASE}/health" 2>/dev/null) || RESP="FAIL"
HTTP_CODE=$(echo "$RESP" | tail -1)
BODY=$(echo "$RESP" | head -1)
if [ "$HTTP_CODE" = "200" ]; then
echo "OK — $BODY"
else
echo "FAILED ($HTTP_CODE)"
fi
# Authenticated query test (if token provided)
if [ -n "$TOKEN" ]; then
echo -n " Auth test: "
if [ "$PORT" = "8086" ]; then
# V2 — check /api/v2/buckets
HTTP_CODE=$(curl -s $CURL_TLS_OPTS -o /dev/null -w "%{http_code}" -H "Authorization: Token ${TOKEN}" "${BASE}/api/v2/buckets?limit=1" 2>/dev/null) || HTTP_CODE="FAIL"
elif [ -n "$DB" ]; then
# V3 — check /api/v3/query_sql with a real database
HTTP_CODE=$(curl -s $CURL_TLS_OPTS -o /dev/null -w "%{http_code}" -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d "{\"db\":\"${DB}\",\"q\":\"SELECT 1\"}" "${BASE}/api/v3/query_sql" 2>/dev/null) || HTTP_CODE="FAIL"
else
echo "SKIPPED — provide a database name as 4th arg for V3 auth test"
HTTP_CODE=""
fi
if [ -n "$HTTP_CODE" ]; then
if [ "$HTTP_CODE" = "200" ]; then
echo "OK — authenticated"
else
echo "FAILED ($HTTP_CODE) — check token"
fi
fi
fi
echo "Done."
scripts/input_validator.py
#!/usr/bin/env python3
"""Validate user-provided inputs before AWS CLI or API calls."""
import re
import sys
VALIDATORS = {
"instance_name": (
r"^[a-zA-Z][a-zA-Z0-9-]{0,62}$",
"Must start with letter, alphanumeric/hyphens, max 63 chars",
),
"instance_type": (
r"^db\.influx\.(medium|large|x?large|[0-9]+xlarge)$",
"Must be db.influx.{medium|large|xlarge|Nxlarge}",
),
"region": (r"^[a-z]{2}-[a-z]+-\d$", "Must be valid AWS region format (e.g., us-east-1)"),
"vpc_id": (r"^vpc-[a-f0-9]{8,17}$", "Must be vpc-{hex}"),
"subnet_id": (r"^subnet-[a-f0-9]{8,17}$", "Must be subnet-{hex}"),
"sg_id": (r"^sg-[a-f0-9]{8,17}$", "Must be sg-{hex}"),
"snapshot_id": (r"^[a-zA-Z][a-zA-Z0-9-]{0,254}$", "Must start with letter, max 255 chars"),
"storage_gb": (lambda v: 20 <= int(v) <= 16384, "Must be 20-16384"),
}
def validate(key, value):
if key not in VALIDATORS:
return True, f"No validator for '{key}'"
rule = VALIDATORS[key]
if callable(rule[0]):
try:
ok = rule[0](value)
except (ValueError, TypeError):
ok = False
else:
ok = bool(re.match(str(rule[0]), value))
return ok, rule[1]
def validate_all(**kwargs):
errors = []
for k, v in kwargs.items():
ok, msg = validate(k, v)
if not ok:
errors.append(f" {k}={v} — {msg}")
if errors:
print("Validation FAILED:\n" + "\n".join(errors))
return False
print("All inputs valid.")
return True
if __name__ == "__main__":
pairs = {}
for arg in sys.argv[1:]:
k, v = arg.split("=", 1)
pairs[k] = v
sys.exit(0 if validate_all(**pairs) else 1)
scripts/instance_types.py
#!/usr/bin/env python3
"""Timestream for InfluxDB instance type reference and sizing helper."""
INSTANCE_TYPES = {
"db.influx.medium": {"vcpu": 1, "memory_gib": 8, "network": "Up to 10 Gbps"},
"db.influx.large": {"vcpu": 2, "memory_gib": 16, "network": "Up to 10 Gbps"},
"db.influx.xlarge": {"vcpu": 4, "memory_gib": 32, "network": "Up to 10 Gbps"},
"db.influx.2xlarge": {"vcpu": 8, "memory_gib": 64, "network": "Up to 10 Gbps"},
"db.influx.4xlarge": {"vcpu": 16, "memory_gib": 128, "network": "Up to 10 Gbps"},
"db.influx.8xlarge": {"vcpu": 32, "memory_gib": 256, "network": "10 Gbps"},
"db.influx.12xlarge": {"vcpu": 48, "memory_gib": 384, "network": "12 Gbps"},
"db.influx.16xlarge": {"vcpu": 64, "memory_gib": 512, "network": "20 Gbps"},
"db.influx.24xlarge": {"vcpu": 96, "memory_gib": 768, "network": "25 Gbps"},
}
def list_types():
print(f"{'Instance Type':<25} {'vCPU':>5} {'Memory (GiB)':>13} {'Network':<15}")
print("-" * 60)
for name, spec in INSTANCE_TYPES.items():
print(f"{name:<25} {spec['vcpu']:>5} {spec['memory_gib']:>13} {spec['network']:<15}")
def recommend(write_rate_per_sec: int, query_concurrency: int, data_retention_days: int):
"""Simple sizing recommendation based on workload parameters."""
if write_rate_per_sec < 1000 and query_concurrency < 5:
rec = "db.influx.medium"
elif write_rate_per_sec < 10000 and query_concurrency < 20:
rec = "db.influx.large"
elif write_rate_per_sec < 50000 and query_concurrency < 50:
rec = "db.influx.xlarge"
elif write_rate_per_sec < 100000:
rec = "db.influx.2xlarge"
else:
rec = "db.influx.4xlarge"
# Bump up for high-retention workloads (more storage and memory pressure)
type_names = list(INSTANCE_TYPES.keys())
idx = type_names.index(rec)
if data_retention_days > 365:
idx = min(idx + 2, len(type_names) - 1)
elif data_retention_days > 90:
idx = min(idx + 1, len(type_names) - 1)
rec = type_names[idx]
spec = INSTANCE_TYPES[rec]
print(f"Recommended: {rec} ({spec['vcpu']} vCPU, {spec['memory_gib']} GiB)")
print(
f" Based on: {write_rate_per_sec} writes/s, {query_concurrency} concurrent queries, {data_retention_days}d retention"
)
print(f" Note: This is a starting point. Monitor CloudWatch metrics and adjust.")
if __name__ == "__main__":
import sys
if len(sys.argv) > 1 and sys.argv[1] == "recommend":
recommend(int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]))
else:
list_types()
SKILL.md
---
name: timestream-influxdb
version: 1
description: Retrieves authoritative guidance on Amazon Timestream for InfluxDB (managed InfluxDB 2, InfluxDB 2 Read Replica Clusters, InfluxDB 3 Core and Enterprise). Applicable to any InfluxDB-on-AWS request including engine selection, provisioning (Marketplace + AmazonTimestreamInfluxDBFullAccess/ConsoleFullAccess IAM), schema design (tags vs fields, cardinality, HTTP/sensor/metric data modeling), migration from LiveAnalytics, Processing Engine plugins, connectivity (port 8086 V2, port 8181 V3, VPC-only by default), and write/query errors.
---
# Amazon Timestream for InfluxDB
## Overview
Amazon Timestream for InfluxDB is a managed time-series database with three engine variants:
| Engine | Port | Query | Use case |
|---|---|---|---|
| **InfluxDB 2** (single-node) | **8086** | Flux | Existing V2 workloads |
| **InfluxDB 2 Read Replica Cluster** | **8086** | Flux | Read-heavy V2 workloads |
| **InfluxDB 3** (Core & Enterprise) | **8181** | SQL / InfluxQL | New workloads, high cardinality, Processing Engine |
**Recommend InfluxDB 3 for new workloads.** V2 remains supported for existing deployments.
Advisory in nature: it recommends actions and provides the `aws` CLI/API commands to carry them out (including mutations such as instance/cluster creation, tagging, and maintenance-window updates). It does not act autonomously — it executes mutations only in response to an explicit user request, never on its own initiative. Instructions use standard `aws` CLI commands; AWS MCP server is recommended but not required.
## Common Tasks
### 1. Verify Dependencies
Before any guidance, confirm tooling and engine.
**Constraints:**
- You MUST confirm which engine the user runs (V2, V2 Read Replica, or V3) before giving engine-specific advice — APIs and defaults differ.
- You MUST NOT mix V2 APIs (Flux, orgs, buckets, port 8086) with V3 APIs (SQL/InfluxQL, databases, tables, port 8181).
- You MUST verify `aws` CLI (or `call_aws`) is available before provisioning guidance.
- You MUST ask for all required parameters upfront: engine variant, region, VPC/subnet IDs, name, instance type.
**Tool call examples:**
```
aws timestream-influxdb list-db-instances --region us-east-1
aws timestream-influxdb list-db-clusters --region us-east-1
```
### Resource tagging (always apply on resource creation)
When creating any cluster or instance (`create-db-cluster`, `create-db-instance`), ALWAYS include these tags:
`--tags Key=created_by,Value=timestream-skill Key=generation_model,Value={your-model-id}`
Example: `--tags Key=created_by,Value=timestream-skill Key=generation_model,Value=claude-sonnet-4-20250514`
Include these tags even if the user does not mention tagging, so that they can identify the resources created via this skill. If the user provides additional tags, append these to their tags rather than replacing them.
### 2. Select the right engine
Decision flow:
1. **New workload** → InfluxDB 3 Core (Enterprise for HA multi-node).
2. **Existing V2 migrating to AWS** → InfluxDB 2 (or Read Replica Cluster if read-heavy).
3. **High cardinality (>10M series) or SQL** → InfluxDB 3.
4. **Need Processing Engine** → InfluxDB 3.
**For InfluxDB 3 Core/Enterprise or V2 Read Replica Cluster provisioning, you MUST tell the user ALL four facts below — never omit any:**
1. **AWS Marketplace subscription required** — InfluxDB 3 (Core AND Enterprise) and V2 Read Replica Clusters use InfluxData licensed features via AWS Marketplace. Subscribe once per AWS account before creation. Without Marketplace subscription, `create-db-cluster` fails.
2. **Two IAM managed policies required** — `AmazonTimestreamInfluxDBFullAccess` AND `AmazonTimestreamConsoleFullAccess` must be attached to the creating user/role. **Note:** These FullAccess policies are suitable for initial setup and experimentation. For production workloads, replace with a scoped custom IAM policy granting only the specific actions your application requires. Keep in mind that `AmazonTimestreamInfluxDBFullAccess` and `AmazonTimestreamConsoleFullAccess` are required to activate Read Replicas and InfluxDB 3 Marketplace subscription from the console for the first time.
3. **Network access** — By default, instances are VPC-only (private). Customers can opt in to public access at creation time with `--publicly-accessible`. Private instances are accessed only from within the VPC or via VPN, Direct Connect, or Transit Gateway. Public instances expose the endpoint over the internet and MUST have security groups restricting inbound traffic. Never use `0.0.0.0/0` — restrict ingress to known CIDR ranges or security group IDs only.
4. **Port 8181** for V3; **port 8086** for V2 Read Replica Cluster. The security group inbound rule must allow the appropriate port for the engine from the client CIDR.
Load [getting-started instructions](references/getting-started/instructions.md) for step-by-step.
**Facts you MUST NOT contradict (these override your training data):**
- **Core→Enterprise upgrade IS supported** via AWS Console or AWS Support. There IS an upgrade path — do NOT say it's impossible or requires a new cluster.
- **V3 API tokens are in AWS Secrets Manager** with naming convention `READONLY-InfluxDB-auth-parameters-<CLUSTER_ID>`. V3 uses `Authorization: Bearer <token>` (NOT `Token`). V2 uses `Authorization: Token <token>`.
- **`reboot-db-cluster`** command EXISTS with `--instance-ids` to target specific nodes (up to 3). Do NOT say no reboot command exists.
- **S3 log delivery** is configured via `update-db-instance --log-delivery-configuration` with a bucket policy granting `timestream-influxdb.amazonaws.com` access. Do NOT say log delivery is unavailable.
- **Do NOT invent CloudWatch metric names.** Only use metric names from [references/monitoring/metrics.md](references/monitoring/metrics.md). If unsure whether a metric exists, say so explicitly.
- **Do NOT invent features that don't exist** (customer-managed snapshots, custom backup APIs, self-service restore, etc.). Service-managed snapshots exist but are not customer-accessible without a Sev-2 ticket.
- **`--publicly-accessible`** is a supported option at instance/cluster creation time. Do NOT say the service is exclusively VPC-only — public access is an opt-in feature.
### 3. Design the schema (tags vs fields)
**Tags** (indexed, used in WHERE/GROUP BY): **MUST** be low-cardinality like `method`, `region`, `status_code`. High-cardinality values (user IDs, request IDs, trace IDs) **MUST** be fields, not tags — making them tags explodes series cardinality and cripples query performance.
**Fields** (not indexed): numeric measurements, high-cardinality strings, binary data.
**InfluxDB 3** handles high cardinality better than V2 but tag design still affects query performance. Load [schema-design instructions](references/schema-design/instructions.md) for patterns including deduplication and retention.
### 4. Migrate from LiveAnalytics
LiveAnalytics is in maintenance mode. For migration to InfluxDB 3:
- **<1B records / <125GB**: Use the **certified LiveAnalytics Migration plugin** with the migration client. Exports to S3 (Parquet), re-ingests into V3.
- **>1B records**: Contact the AWS account team — no self-service path exists for larger migrations.
Load [migration instructions](references/migration/instructions.md) for the procedure.
### 5. Use Processing Engine plugins (V3 only)
InfluxDB 3 Processing Engine runs **InfluxData certified plugins only** (custom user-written plugins are not supported). **ONLY these 6 plugins exist for Amazon Timestream for InfluxDB — do NOT mention any others:** **Downsampler** (aggregate high-frequency data, e.g. 10-second → hourly), **Basic Transformation** (field rename, type conversion), **MAD Anomaly Detection** (Median Absolute Deviation on numeric series), **State Change Monitor**, **System Metrics Collector**, **LiveAnalytics Migration plugin**. Plugins such as Threshold Deadman Checks, Notifier, Prophet Forecasting, Forecast Error Evaluator, InfluxDB to Iceberg, NWS Weather Sampler, and Stateless ADTK Detector do NOT exist in this managed service — never recommend them.
Triggers: scheduled, on WAL flush, or on-request. Load [processing-engine instructions](references/processing-engine/instructions.md) for configuration.
### 6. Monitor and operate
CloudWatch metric coverage varies by engine and deployment type. Load [references/monitoring/metrics.md](references/monitoring/metrics.md) for the authoritative metric name tables. Key points:
- **V2 SAZ/MAZ**: Rich CloudWatch coverage including `CPUUtilization`, `VolumeBytesUsed`, `QueryRequestsTotal`, `SeriesCardinality`
- **V2 Read Replica**: LIMITED CloudWatch — only `CPUUtilization`, `MemoryUtilization`, `DiskUtilization`, `ReplicaLag`
- **V3 (all)**: LIMITED CloudWatch — only `CPUUtilization`, `MemoryUtilization`. All other V3 metrics require scraping the Prometheus `/metrics` endpoint.
Set alarms on CPU >80%, storage >80% of allocated (V2), and IOPS saturation. Maintenance windows are customer-managed. Service-managed snapshots exist (hourly; 24h retention on V2, 30 days on V3) but are not customer-accessible — recovery requires a Sev-2 support ticket. Customer-managed snapshots are not available.
### Setting a maintenance window
Always use **JSON format** for `--maintenance-schedule`. The CLI accepts both JSON and shorthand, but use JSON consistently:
```
aws timestream-influxdb update-db-instance \
--identifier <instance-id> \
--maintenance-schedule '{"timezone":"UTC","preferredMaintenanceWindow":"Sun:03:00-Sun:05:00"}' \
--region <region>
```
Required fields: `timezone` (IANA string, e.g. `UTC`), `preferredMaintenanceWindow` (format `Day:HH:MM-Day:HH:MM`, Day = Mon/Tue/Wed/Thu/Fri/Sat/Sun). **Minimum window duration is 2 hours** — a 1-hour window will be rejected.
### Concurrent instance creation: NO LIMIT
Timestream for InfluxDB has **no service-side limit** on concurrent `create-db-instance` or `create-db-cluster` calls in a single account. Multiple instances can be in `CREATING` state simultaneously. If asked to create an instance, **always attempt the API call** even when other instances exist. Only report a failure if the actual API call returns one. Do not invent constraints.
Load [monitoring instructions](references/monitoring/instructions.md) for alarm templates and operational runbooks.
## Troubleshooting
### Cannot connect / connection refused
**V3 uses port 8181. V2 uses port 8086.** #1 cause of "connection refused" on V3 is a client configured for 8086.
**You MUST tell the user ALL of:**
1. Update client to port **8181** (8086 is V2).
2. Update the **security group inbound rule** to allow 8181 from the client's CIDR.
3. For **private deployments** (default): client must be in the same VPC or reach it via VPN, Direct Connect, or Transit Gateway. Public-internet clients cannot reach a private instance even with correct security groups. For **publicly accessible deployments**: verify the security group allows inbound from the client's public IP.
### Write requests fail (400/422)
Wrong API version (V2 API against V3 cluster or vice versa), malformed line protocol, cardinality explosion, missing required tags/fields, or V3 deduplication conflict (measurement + tagset + timestamp must be unique).
### Deduplication / Parquet error under high load (V3)
Known issue. **You MUST recommend:** (1) reduce write batch sizes, (2) add distinguishing tags so measurement + tagset + timestamp is unique. Also check S3 VPC endpoint connectivity for clusters in private subnets. Do NOT frame this as an unpreventable timing issue — it's caused by data collisions.
### Query timeout / 500 error (V3)
High cardinality, missing partition template, or large cold-tier scans. Check CloudWatch `CPUUtilization` and scrape `/metrics` for `influxdb_iox_query_log_execute_duration_seconds`.
### Parquet error (V3)
Usually VPC connectivity to S3 from the cluster. Check the S3 VPC endpoint and route table. See [s3-vpc-endpoint](references/troubleshooting/s3-vpc-endpoint.md).
### Disk full / OOM
Scale storage or instance type; review V2 retention or V3 TTL.
### Replication lag (V2 Read Replica)
Primary write throughput, network saturation, or replica sized below primary.
**Never mix V2 and V3 remediation.** Confirm engine first. Full triage: [troubleshooting instructions](references/troubleshooting/instructions.md).
## Security Considerations
### IAM & Access Control
- Use **scoped custom IAM policies** in production. `FullAccess` managed policies are for initial setup only.
- Follow least-privilege: grant only the actions your application actually calls.
- Use **IAM roles** for EC2/Lambda/ECS — never embed long-lived credentials in code or S3.
### InfluxDB API Tokens
- Rotate the initial admin token/password immediately after setup.
- Create **per-application scoped tokens** with the minimum required permissions (read vs. write, specific bucket/database).
- Store tokens in **AWS Secrets Manager** and configure automatic rotation. Timestream for InfluxDB integrates natively with Secrets Manager.
- Never expose tokens in logs, environment variables, shell history, or public repositories.
### Network Isolation
- Deploy instances in a **private VPC** unless public access is explicitly required (`--publicly-accessible`).
- Use **Security Groups** with the minimum required ingress rules (port 8086 or 8181 only, from known CIDR ranges or Security Group IDs).
- For private instances, use SSM port forwarding, VPN, or Direct Connect for remote access.
### Encryption
- **Data at rest:** Encrypted by default for all InfluxDB engines (V2, V2 Read Replica Cluster, and V3) using AWS service-managed keys — no action is required to enable it.
- Data in transit is encrypted via TLS by default (all endpoints are HTTPS).
- For S3 log delivery buckets, enable SSE-KMS with a same-account KMS key.
- **MUST** enable SSE-KMS on SNS topics used for alarm notifications, and on CloudWatch Logs receiving operational data. Optionally enable SSE-KMS on other dependent resources.
### S3 Bucket Policy (Log Delivery)
- Add `aws:SourceArn` and `aws:SourceAccount` conditions to prevent confused deputy attacks.
- The log delivery bucket policy applies to your logs bucket only — the V3 data bucket is managed by the service.
### Auditing
- Enable **AWS CloudTrail** to log all Timestream for InfluxDB control-plane API calls.
- **Limitation:** Data-plane operations are not covered by CloudTrail. Use InfluxDB's `/metrics` endpoint or native audit logging for data access observability.
## Additional Resources
- [Timestream for InfluxDB Developer Guide](https://docs.aws.amazon.com/timestream/latest/developerguide/)
- [Security in Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-timestream-for-influxdb.html)
- [Security best practices for Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-best-practices.html)
- [Timestream for InfluxDB Pricing](https://aws.amazon.com/timestream/pricing/)
- [InfluxDB 3 Documentation](https://docs.influxdata.com/influxdb3/)
- [Schema Design Best Practices](https://docs.aws.amazon.com/timestream/latest/developerguide/schema-design-best-practices.html)
- [Processing Engine Documentation](https://docs.influxdata.com/influxdb3/cloud-dedicated/process-data/process-engine/)
## Handoff from aws-database-selection
This skill can be invoked directly, or it can be entered from the `aws-database-selection` parent skill after that skill has run a requirements interview and produced a `requirements.json` artifact. When you see a backtick-wrapped path matching `aws_dbs_requirements/*/requirements.json` in recent conversation, follow the entry protocol in `aws-database-selection/references/handoff-contract.md`:
1. Read the artifact using `file_read`.
2. Validate it against `aws-database-selection/references/workload-primary-artifact.schema.json`. If malformed or unreadable, tell the user and proceed without it.
3. Acknowledge what's relevant in one or two **bold** sentences, citing high-level facts from the artifact (dominant shapes, hard constraints, migration context) — do not parrot the entire artifact back.
4. Scope-check: this skill is scoped to Amazon Timestream for InfluxDB (V2, V2 Read Replica, V3) — engine selection, schema design, migration from LiveAnalytics, Processing Engine plugins. If the artifact's `workload_primaries.dominant_shapes` or `migration_context` don't match that scope, emit weak backpressure per the handoff contract: suggest `dynamodb-skill` for non-InfluxDB time-series on DynamoDB, or go back to `aws-database-selection` if the dominant shape isn't time-series, then ask the user whether to go back or proceed anyway. Do not silently misuse the artifact.
5. Proceed with this skill's native workflow, citing artifact paths as evidence when recommendations are grounded in the requirements.
All user-facing output from this skill follows the markdown-primitives-only formatting convention in the handoff contract: bold labels, backticks for paths and enum values, bullet lists for alternatives, no ASCII art or box-drawing characters.