Documentation Best Practices

8 minute read

Documentation Best Practices

Well-written documentation is critical for provider adoption and user success. This chapter covers best practices for creating and maintaining high-quality documentation.

Writing Style

1. Clear and Concise

✅ Good:

The `backup_retention_days` attribute specifies how many days to retain automated backups. Valid range: 1-35. Required when `backup_enabled` is `true`.

❌ Bad:

This thing controls backups or something.

2. Active Voice

✅ Good:

The provider creates a cache instance in your account.

❌ Bad:

A cache instance is created by the provider in your account.

3. Present Tense

✅ Good:

The cache uses Redis 7.0 by default.

❌ Bad:

The cache will use Redis 7.0 by default.

Structure

Logical Organization

# Resource Documentation Template

1. **Title and Description**
   - Clear resource name
   - Brief description of purpose
   
2. **Example Usage**
   - Basic example first
   - Advanced examples after
   
3. **Schema**
   - Required attributes
   - Optional attributes
   - Computed (read-only) attributes
   
4. **Additional Information**
   - Timeouts
   - Import instructions
   
5. **Common Patterns**
   - Frequent use cases
   
6. **Troubleshooting**
   - Common issues and solutions

Progressive Disclosure

Start simple, add complexity gradually:

## Example Usage

### Basic Configuration

```terraform
resource "cachecloud_cache" "basic" {
  name      = "my-cache"
  engine    = "redis"
  node_type = "cache.t3.micro"
}

With High Availability

resource "cachecloud_cache" "ha" {
  name      = "ha-cache"
  engine    = "redis"
  node_type = "cache.m5.large"
  num_nodes = 3
  
  multi_az_enabled = true
  automatic_failover_enabled = true
}

Production Configuration

resource "cachecloud_cache" "production" {
  name      = "prod-cache"
  engine    = "redis"
  version   = "7.0"
  node_type = "cache.m5.xlarge"
  num_nodes = 3
  
  # High availability
  multi_az_enabled           = true
  automatic_failover_enabled = true
  
  # Backups
  backup_enabled        = true
  backup_retention_days = 30
  
  # Security
  encryption_at_rest_enabled    = true
  encryption_in_transit_enabled = true
  
  # Monitoring
  monitoring_enabled = true
}

## Code Examples

### Complete and Runnable

**✅ Good: Complete example**
```terraform
terraform {
  required_providers {
    cachecloud = {
      source  = "example/cachecloud"
      version = "~> 1.0"
    }
  }
}

provider "cachecloud" {
  api_key = var.cachecloud_api_key
}

resource "cachecloud_cache" "example" {
  name      = "example-cache"
  engine    = "redis"
  node_type = "cache.t3.micro"
}

output "endpoint" {
  value = cachecloud_cache.example.endpoint
}

❌ Bad: Incomplete snippet

resource "cachecloud_cache" "example" {
  name = "cache"
}

Realistic Examples

✅ Good: Real-world scenario

# Production API cache with monitoring
resource "cachecloud_cache" "api_cache" {
  name      = "${var.environment}-api-cache"
  engine    = "redis"
  version   = "7.0"
  node_type = var.cache_node_type
  num_nodes = var.cache_num_nodes
  
  multi_az_enabled = var.environment == "production"
  backup_enabled   = var.environment == "production"
  
  tags = merge(
    var.common_tags,
    {
      Name        = "${var.environment}-api-cache"
      Component   = "caching"
      ManagedBy   = "terraform"
    }
  )
}

# CloudWatch alarm for high CPU
resource "aws_cloudwatch_metric_alarm" "cache_cpu" {
  alarm_name          = "${var.environment}-cache-high-cpu"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "CacheCloud"
  period              = "300"
  statistic           = "Average"
  threshold           = "75"
  
  dimensions = {
    CacheId = cachecloud_cache.api_cache.id
  }
  
  alarm_actions = [aws_sns_topic.alerts.arn]
}

❌ Bad: Toy example

resource "cachecloud_cache" "test" {
  name = "test"
}

Tested Examples

# Create test directory
mkdir -p docs/examples/basic-cache

# Write example
cat > docs/examples/basic-cache/main.tf <<EOF
terraform {
  required_providers {
    cachecloud = {
      source  = "example/cachecloud"
      version = "~> 1.0"
    }
  }
}

provider "cachecloud" {}

resource "cachecloud_cache" "example" {
  name      = "docs-example-\${random_string.suffix.result}"
  engine    = "redis"
  node_type = "cache.t3.micro"
}

resource "random_string" "suffix" {
  length  = 8
  special = false
  upper   = false
}

output "endpoint" {
  value = cachecloud_cache.example.endpoint
}
EOF

# Test example
cd docs/examples/basic-cache
terraform init
terraform validate
terraform fmt -check

Attribute Documentation

Comprehensive Descriptions

✅ Good: Detailed description

- `backup_window` (String) Daily time range during which automated backups are created, specified in UTC. Format: `HH:MM-HH:MM` (e.g., `03:00-05:00`). The window must be at least 60 minutes and cannot overlap with `maintenance_window`. Defaults to a randomly selected 60-minute window between 00:00-06:00 UTC.

❌ Bad: Minimal description

- `backup_window` (String) Backup time window.

Include Constraints

### Required

- `name` (String) The name of the cache. Must be 3-63 characters long, start with a lowercase letter, and contain only lowercase letters, numbers, and hyphens. Must be unique within your account and region.

- `engine` (String) The cache engine type. Valid values: `redis`, `memcached`.

- `node_type` (String) The compute and memory capacity of the nodes. See [Node Types](#node-types) for available options.

### Optional

- `num_nodes` (Number) Number of cache nodes in the cluster. Valid range: 1-90 for Redis, 1-20 for Memcached. Defaults to `1`.

- `port` (Number) The port number on which the cache accepts connections. Valid range: 1024-65535. Redis defaults to `6379`, Memcached to `11211`.

- `backup_retention_days` (Number) Number of days to retain automated backups. Valid range: 1-35. Required if `backup_enabled` is `true`. Not applicable for Memcached.

Document Defaults

# ✅ Good: Clear default
- `node_type` (String) The instance type. See [pricing](https://example.com/pricing) for available types. Defaults to `cache.t3.micro`.

# ❌ Bad: No default specified
- `node_type` (String) The instance type.

Show Valid Values

# ✅ Good: Enumerated values
- `engine` (String) The cache engine. Valid values: `redis`, `memcached`.

# ✅ Good: Range
- `port` (Number) Connection port. Valid range: 1024-65535.

# ✅ Good: Format
- `backup_window` (String) Backup time window in UTC. Format: `HH:MM-HH:MM` (e.g., `03:00-05:00`).

Deprecation Notices

Clear Communication

## Deprecated Attributes

### `legacy_mode`

**Deprecated:** This attribute is deprecated and will be removed in version 2.0. Use the `mode` attribute instead.

**Migration:**

```terraform
# Old (deprecated)
resource "cachecloud_cache" "old" {
  name        = "my-cache"
  legacy_mode = true
}

# New (recommended)
resource "cachecloud_cache" "new" {
  name = "my-cache"
  mode = "legacy"
}

Timeline:

  • Version 1.5: legacy_mode deprecated, warnings added
  • Version 2.0: legacy_mode removed ```

Diagrams and Visual Aids

Architecture Diagrams

## High Availability Architecture

                ┌─────────────────┐
                │   Application   │
                └────────┬────────┘
                         │
                         ▼
                ┌─────────────────┐
                │  Load Balancer  │
                └────────┬────────┘
                         │
            ┌────────────┼────────────┐
            │            │            │
            ▼            ▼            ▼
    ┌──────────┐  ┌──────────┐  ┌──────────┐
    │  Primary │  │ Replica  │  │ Replica  │
    │    AZ-A  │  │    AZ-B  │  │    AZ-C  │
    └──────────┘  └──────────┘  └──────────┘
         │              │              │
         └──────────────┴──────────────┘
                Replication ``` ```

State Diagrams

## Cache Lifecycle

┌─────────┐
│ Created │
└────┬────┘
     │
     ▼
┌─────────┐     Error    ┌──────────────┐
│Creating ├─────────────▶│CreateFailed  │
└────┬────┘               └──────────────┘
     │ Success
     ▼
┌──────────┐
│Available │◄──────┐
└────┬─────┘       │
     │             │
     ▼             │
┌──────────┐      │
│Modifying ├──────┘
└────┬─────┘
     │
     ▼
┌──────────┐
│ Deleting │
└────┬─────┘
     │
     ▼
┌─────────┐
│ Deleted │
└─────────┘ ``` ```

Comparison Tables

## Node Type Comparison

| Type | vCPU | Memory | Network | Best For |
|------|------|--------|---------|----------|
| cache.t3.micro | 2 | 0.5 GB | Low-Moderate | Development, testing |
| cache.t3.small | 2 | 1.4 GB | Low-Moderate | Small workloads |
| cache.m5.large | 2 | 6.4 GB | Up to 10 Gbps | Production workloads |
| cache.m5.xlarge | 4 | 12.9 GB | Up to 10 Gbps | High-traffic applications |
| cache.r5.large | 2 | 13.5 GB | Up to 10 Gbps | Memory-intensive workloads |

Version Documentation

Changelog

# Changelog

## [1.2.0] - 2026-06-30

### Added
- Support for Redis 7.0
- New `log_delivery_configuration` attribute
- Data source `cachecloud_engine_versions`

### Changed
- Default engine version changed from 6.2 to 7.0
- Improved error messages for authentication failures

### Deprecated
- `legacy_mode` attribute (use `mode` instead)

### Fixed
- Import now correctly handles multi-region caches
- Timeout handling for large cache deletions

## [1.1.0] - 2026-05-15

### Added
- Support for cluster mode
- New `cluster_mode_enabled` attribute

### Fixed
- State drift detection for tags

Upgrade Guides

# Upgrade Guide: v1.x to v2.0

## Breaking Changes

### 1. Removed `legacy_mode` Attribute

**Old:**
```terraform
resource "cachecloud_cache" "example" {
  legacy_mode = true
}

New:

resource "cachecloud_cache" "example" {
  mode = "legacy"
}

Migration:

# Update configurations
find . -name "*.tf" -exec sed -i 's/legacy_mode =/mode =/g' {} \;

# Run terraform plan to verify
terraform plan

2. Default Engine Version Changed

Version 2.0 defaults to Redis 7.0 instead of 6.2.

Action Required: Pin version if you need 6.2:

resource "cachecloud_cache" "example" {
  engine  = "redis"
  version = "6.2"  # Explicitly set
}

3. Authentication Changes

IAM authentication now uses auth_method instead of use_iam.

Old:

provider "cachecloud" {
  use_iam = true
}

New:

provider "cachecloud" {
  auth_method = "iam"
}

Upgrade Process

  1. Review Changes
    # Check current provider version
    terraform version
    
  2. Update Provider Version
    terraform {
      required_providers {
        cachecloud = {
          source  = "example/cachecloud"
          version = "~> 2.0"
        }
      }
    }
    
  3. Test in Non-Production
    terraform init -upgrade
    terraform plan
    
  4. Apply Changes
    terraform apply
    

    ```

Accessibility

Alt Text for Images

# ✅ Good: Descriptive alt text
![High availability architecture showing primary cache with two read replicas across three availability zones](images/ha-architecture.png)

# ❌ Bad: Generic alt text
![diagram](images/ha-architecture.png)

Semantic HTML

# Use proper heading hierarchy
# Main Page Title

## Section Heading

### Subsection Heading

#### Detail Heading

Color Contrast

# Avoid color-only indicators

# ❌ Bad: Color only
> This is important (shown in red)

# ✅ Good: Text indicator
> ⚠️ **Warning:** This is important

Consistency

Terminology

Maintain consistent terminology:

# ✅ Consistent
- "cache instance" throughout documentation
- "API key" (not "api key", "API Key", or "apikey")
- "Multi-AZ" (not "multi-az", "MultiAZ", or "multi-AZ")

# Create glossary
## Glossary

- **Cache Instance**: A managed cache deployment
- **Cluster Mode**: Redis configuration with multiple shards
- **Multi-AZ**: Deployment across multiple availability zones

Formatting

# ✅ Consistent formatting
- Attribute names: `backticks`
- Values: `"quoted"`
- Placeholders: `<angle-brackets>`
- File paths: `code format`

Example:
Set `backup_enabled` to `"true"` in `main.tf`.
Replace `<cache-id>` with your actual cache ID.

Maintenance

Review Cycle

# Documentation review checklist

## Monthly Review
- [ ] Verify all examples still work
- [ ] Check for outdated version references
- [ ] Update screenshots if UI changed
- [ ] Review and address user feedback

## Per Release
- [ ] Update changelog
- [ ] Document new features
- [ ] Update migration guides
- [ ] Test all code examples
- [ ] Update version numbers

Automated Validation

# .github/workflows/docs-validation.yml
name: Documentation Validation

on:
  pull_request:
    paths:
      - 'docs/**'
      - 'examples/**'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Check markdown links
        uses: gaurav-nelson/github-action-markdown-link-check@v1
      
      - name: Spell check
        uses: rojopolis/spellcheck-github-actions@v0
        
      - name: Validate examples
        run: |
          for dir in examples/*/; do
            cd "$dir"
            terraform init
            terraform validate
            cd -
          done

Key Takeaways

  • ✅ Write clearly and concisely in active voice
  • ✅ Organize content logically with progressive disclosure
  • ✅ Provide complete, tested, realistic examples
  • ✅ Document all attributes with constraints and defaults
  • ✅ Include diagrams for complex concepts
  • ✅ Maintain consistency in terminology and formatting
  • ✅ Keep documentation up to date with code
  • ✅ Make documentation accessible
  • ✅ Automate validation where possible
  • ✅ Regularly review and update based on feedback

What’s Next?

Practice generating and customizing documentation in a hands-on lab.

Next: Documentation Lab →


Previous: ← Guides & Examples
Next: Documentation Lab →

Last updated: June 30, 2026

Updated: