> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Service Equivalents

**Service equivalents** define how Tensor9 maps cloud-specific managed services in your [origin stack](/fundamentals/origin-stacks) to their functional equivalents in the target [appliance's](/fundamentals/appliances) environment. During compilation, Tensor9 maps resources from your origin stack to corresponding services in AWS, Google Cloud, Azure, Digital Ocean, or private environments.

## Overview

Cloud providers offer similar services under different names and APIs:

* AWS RDS PostgreSQL vs. Google Cloud SQL vs. Azure Database for PostgreSQL
* AWS S3 vs. Google Cloud Storage vs. Azure Blob Storage
* AWS ElastiCache vs. Google Memorystore vs. Azure Cache for Redis

Tensor9 handles the mapping between these provider-specific implementations. You define your infrastructure using one cloud provider's resources, and Tensor9 maps them to the target environment.

## How service equivalents work

When you create a [release](/fundamentals/deployments) for a specific appliance, Tensor9 compiles your origin stack through several steps:

<Steps>
  <Step title="Analyze origin stack">
    Tensor9 identifies all cloud-specific resources in your origin stack.
  </Step>

  <Step title="Map to functional equivalents">
    Each resource is mapped to its functional equivalent based on the target [form factor](/fundamentals/key-concepts#form-factor).
  </Step>

  <Step title="Map resource definitions">
    The resource definition is mapped to use the target cloud's provider and API.
  </Step>

  <Step title="Preserve configuration semantics">
    Configuration semantics (storage size, instance type, performance characteristics) are preserved in the mapping.
  </Step>

  <Step title="Generate deployment stack">
    A deployment stack ready to deploy in the target environment is generated.
  </Step>
</Steps>

This process is driven by Tensor9's **service equivalents registry**, which maintains mappings between functionally equivalent services across cloud providers and deployment environments.

## Service equivalents registry

Tensor9 groups services into equivalent sets based on their function. When compiling for a specific form factor, Tensor9 automatically selects the appropriate equivalent from the target environment.

| Service Category                   | AWS                                   | Google Cloud                       | Azure                         | DigitalOcean                       | On-Prem                                   |
| ---------------------------------- | ------------------------------------- | ---------------------------------- | ----------------------------- | ---------------------------------- | ----------------------------------------- |
| **Containers**                     | EKS, ECS                              | GKE                                | AKS                           | DOK                                | Kubernetes                                |
| **Functions**                      | Lambda                                | Cloud Functions                    | Azure Functions               | Functions                          | Knative (unmanaged)                       |
| **Networking**                     | VPC                                   | VPC                                | VNet                          | -                                  | -                                         |
| **Load balancing**                 | Load Balancer                         | Load Balancer                      | Load Balancer                 | Load Balancer                      | Cloudflare (optional)                     |
| **DNS**                            | Route 53                              | Cloud DNS                          | Azure DNS                     | DigitalOcean DNS                   | Cloudflare (optional)                     |
| **Identity and access management** | IAM                                   | IAM                                | IAM                           | -                                  | -                                         |
| **Secrets management**             | Secrets Manager                       | Secret Manager                     | Key Vault                     | -                                  | HashiCorp Vault (unmanaged)               |
| **Object storage**                 | S3                                    | Cloud Storage (GCS)                | Azure Blob Storage            | Spaces                             | Backblaze B2, MinIO (unmanaged)           |
| **Databases (PostgreSQL)**         | RDS Aurora PostgreSQL, RDS PostgreSQL | Cloud SQL PostgreSQL               | Azure Database for PostgreSQL | Managed PostgreSQL                 | Neon, CloudNative PostgreSQL (unmanaged)  |
| **Databases (MySQL)**              | RDS Aurora MySQL, RDS MySQL           | Cloud SQL MySQL                    | Azure Database for MySQL      | Managed MySQL                      | PlanetScale, MySQL (unmanaged)            |
| **Databases (MongoDB)**            | DocumentDB                            | Atlas MongoDB                      | Cosmos DB (MongoDB API)       | Managed MongoDB                    | MongoDB Atlas, MongoDB (unmanaged)        |
| **Caching**                        | ElastiCache                           | Memorystore                        | Azure Cache for Redis         | Managed Redis                      | Redis Enterprise Cloud, Redis (unmanaged) |
| **Message streaming**              | MSK (Managed Streaming for Kafka)     | Confluent Cloud, Kafka (unmanaged) | Event Hubs (Kafka compatible) | Confluent Cloud, Kafka (unmanaged) | Confluent Cloud, Kafka (unmanaged)        |
| **Search**                         | OpenSearch Service                    | OpenSearch (unmanaged)             | OpenSearch (unmanaged)        | OpenSearch (unmanaged)             | OpenSearch (unmanaged)                    |
| **Workflow**                       | MWAA (Managed Airflow)                | Cloud Composer                     | Azure Data Factory            | Astronomer, Airflow (unmanaged)    | Astronomer, Airflow (unmanaged)           |

<Note>
  Third-party managed equivalents (Backblaze B2, Neon, PlanetScale, MongoDB Atlas, Redis Enterprise Cloud, Confluent Cloud, Astronomer) require your customers to bring their own credentials and accounts with these services.
</Note>

## Mapping examples

Here are concrete examples of how Tensor9 maps services during compilation.

### Example 1: AWS to Google Cloud

When compiling an AWS-based origin stack for a Google Cloud appliance:

**Origin stack (AWS):**

```terraform theme={null}
resource "aws_db_instance" "postgres" {
  engine         = "postgres"
  instance_class = "db.t3.micro"
  allocated_storage = 20
}

resource "aws_s3_bucket" "data" {
  bucket = "my-app-data-${var.instance_id}"
}

resource "aws_elasticache_cluster" "redis" {
  engine               = "redis"
  node_type            = "cache.t3.micro"
  num_cache_nodes      = 1
}
```

**Compiled deployment stack (Google Cloud):**

<Note>
  The deployment stack below is for illustration purposes only.
  An actual deployment stack is a lot more complicated,  and does not simply contain resources as is shown below.
</Note>

```terraform theme={null}
resource "google_sql_database_instance" "postgres" {
  database_version = "POSTGRES_15"
  tier            = "db-f1-micro"

  settings {
    disk_size = 20
  }
}

resource "google_storage_bucket" "data" {
  name     = "my-app-data-${var.instance_id}"
  location = "US"
}

resource "google_redis_instance" "redis" {
  tier           = "BASIC"
  memory_size_gb = 1
}
```

Tensor9 automatically:

* Replaced `aws_db_instance` with `google_sql_database_instance`
* Replaced `aws_s3_bucket` with `google_storage_bucket`
* Replaced `aws_elasticache_cluster` with `google_redis_instance`
* Preserved configuration (storage size, memory, instance tiers)
* Maintained the `instance_id` variable for resource uniqueness
* Injected replacement service endpoints into application containers (no code changes required)

### Example 2: AWS to private Kubernetes

When compiling an AWS-based origin stack for a private Kubernetes appliance:

**Origin stack (AWS):**

```terraform theme={null}
resource "aws_eks_cluster" "app" {
  name = "my-app-cluster-${var.instance_id}"

  vpc_config {
    subnet_ids = var.subnet_ids
  }
}

resource "aws_db_instance" "postgres" {
  engine         = "postgres"
  instance_class = "db.t3.medium"
  allocated_storage = 100
}

resource "aws_s3_bucket" "artifacts" {
  bucket = "my-app-artifacts-${var.instance_id}"
}
```

**Compiled deployment stack (private Kubernetes):**

<Note>
  The deployment stack below is for illustration purposes only.
  An actual deployment stack is a lot more complicated,  and does not simply contain resources as is shown below.
</Note>

```terraform theme={null}
resource "kubernetes_namespace" "app" {
  metadata {
    name = "my-app-${var.instance_id}"
  }
}

# CloudNative PostgreSQL operator
resource "kubectl_manifest" "postgres" {
  yaml_body = <<-YAML
    apiVersion: postgresql.cnpg.io/v1
    kind: Cluster
    metadata:
      name: postgres
      namespace: my-app-${var.instance_id}
    spec:
      instances: 3
      storage:
        size: 100Gi
      postgresql:
        parameters:
          max_connections: "200"
  YAML
}

# MinIO for object storage
resource "helm_release" "minio" {
  name       = "minio"
  repository = "https://charts.min.io/"
  chart      = "minio"
  namespace  = "my-app-${var.instance_id}"

  set {
    name  = "persistence.size"
    value = "100Gi"
  }
}
```

Tensor9 automatically:

* Replaced the EKS cluster with a Kubernetes namespace
* Replaced AWS RDS with CloudNative PostgreSQL (CNPG) operator
* Replaced S3 with MinIO for private object storage
* Adapted configurations to Kubernetes-native patterns

### Example 3: AWS to Azure

When compiling an AWS-based origin stack for an Azure appliance:

**Origin stack (AWS):**

```terraform theme={null}
resource "aws_lambda_function" "api" {
  function_name = "api-handler-${var.instance_id}"
  runtime       = "python3.11"
  handler       = "index.handler"

  environment {
    variables = {
      DATABASE_URL = aws_db_instance.postgres.endpoint
    }
  }
}

resource "aws_db_instance" "postgres" {
  engine         = "postgres"
  instance_class = "db.t3.small"
}

resource "aws_s3_bucket" "uploads" {
  bucket = "user-uploads-${var.instance_id}"
}
```

**Compiled deployment stack (Azure):**

<Note>
  The deployment stack below is for illustration purposes only.
  An actual deployment stack is a lot more complicated,  and does not simply contain resources as is shown below.
</Note>

```terraform theme={null}
resource "azurerm_linux_function_app" "api" {
  name                = "api-handler-${var.instance_id}"
  resource_group_name = var.resource_group_name
  location            = var.location

  site_config {
    application_stack {
      python_version = "3.11"
    }
  }

  app_settings = {
    DATABASE_URL = azurerm_postgresql_server.postgres.fqdn
  }
}

resource "azurerm_postgresql_server" "postgres" {
  name                = "postgres-${var.instance_id}"
  resource_group_name = var.resource_group_name
  location            = var.location

  sku_name = "B_Gen5_1"
}

resource "azurerm_storage_account" "uploads" {
  name                = "uploads${var.instance_id}"
  resource_group_name = var.resource_group_name
  location            = var.location
}

resource "azurerm_storage_container" "uploads" {
  name                  = "user-uploads"
  storage_account_name  = azurerm_storage_account.uploads.name
}
```

Tensor9 automatically:

* Replaced Lambda with Azure Functions
* Replaced RDS PostgreSQL with Azure Database for PostgreSQL
* Replaced S3 with Azure Blob Storage (storage account + container)
* Preserved environment variables and references between resources
* Injected replacement service endpoints into application containers (no code changes required)

## Wire compatibility and endpoint injection

Service equivalents in Tensor9 are **wire compatible**, meaning your application code doesn't need to change when deploying across different cloud providers. Tensor9 achieves this through **endpoint injection**:

### No code changes required

When services are functionally equivalent, they speak the same protocol:

* **PostgreSQL databases** all use the PostgreSQL wire protocol, whether running on AWS RDS, Google Cloud SQL, or Azure Database for PostgreSQL
* **Redis caches** all use the Redis protocol, whether running on AWS ElastiCache, Google Memorystore, or Azure Cache for Redis
* **Object storage** services all support S3-compatible APIs, whether AWS S3, Google Cloud Storage, Azure Blob Storage, or MinIO
* **Functions** all support the same invocation patterns, whether AWS Lambda, Google Cloud Functions, or Azure Functions

Your application code connects to these services using standard client libraries (e.g., `pg` for PostgreSQL, `redis` for Redis, `boto3` for S3-compatible storage). These libraries work the same regardless of which cloud provider hosts the underlying service.

<Note>
  **Emulation for certain services**: For services like object storage and functions, Tensor9 provides an emulation layer to compensate for a lack of wire compatibility. For example, Azure Blob Storage doesn't natively support the S3 API, so Tensor9 deploys an S3-compatible emulation layer that translates S3 API calls to the native cloud storage API. Similarly, function invocation patterns are normalized across Lambda, Cloud Functions, and Azure Functions. This emulation is transparent to your application code.
</Note>

### Endpoint injection

What changes between cloud providers is the **service endpoint** - the hostname and port your application uses to connect to the service. Tensor9 automatically injects the correct endpoints into your application containers:

**Origin stack definition:**

```terraform theme={null}
resource "aws_db_instance" "postgres" {
  engine         = "postgres"
  instance_class = "db.t3.micro"
}

resource "aws_lambda_function" "api" {
  environment {
    variables = {
      DATABASE_HOST = aws_db_instance.postgres.endpoint
    }
  }
}
```

**Compiled for AWS (unchanged):**

```terraform theme={null}
resource "aws_db_instance" "postgres" {
  engine         = "postgres"
  instance_class = "db.t3.micro"
}

# DATABASE_HOST = postgres.abc123.us-east-1.rds.amazonaws.com:5432
```

**Compiled for Google Cloud:**

```terraform theme={null}
resource "google_sql_database_instance" "postgres" {
  database_version = "POSTGRES_15"
  tier            = "db-f1-micro"
}

# DATABASE_HOST = 10.1.2.3:5432 (Cloud SQL private IP)
```

**Compiled for Azure:**

```terraform theme={null}
resource "azurerm_postgresql_server" "postgres" {
  sku_name = "B_Gen5_1"
}

# DATABASE_HOST = postgres-abc123.postgres.database.azure.com:5432
```

Tensor9 rewrites environment variables, configuration files, and Kubernetes ConfigMaps to inject the correct endpoints for the target cloud provider. Your application code simply reads `DATABASE_HOST` and connects - it doesn't need to know whether it's running on AWS, Google Cloud, or Azure.

### What your code sees

From your application's perspective, connecting to a PostgreSQL database looks identical across all clouds:

```python theme={null}
# This code works the same on AWS, Google Cloud, Azure, or private Kubernetes
import psycopg2
import os

conn = psycopg2.connect(
    host=os.environ['DATABASE_HOST'],
    database=os.environ['DATABASE_NAME'],
    user=os.environ['DATABASE_USER'],
    password=os.environ['DATABASE_PASSWORD']
)
```

Tensor9 ensures the environment variables contain the correct values for each deployment environment. Your code remains unchanged.

## Configuration mapping

When mapping services, Tensor9 preserves the semantic meaning of your configuration:

| Configuration Type                   | How Tensor9 Maps It                                                                                                                                                                                    |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Storage and capacity**             | Disk sizes are mapped to equivalent tiers in the target cloud. Memory allocations are mapped to appropriate instance types. Performance characteristics (IOPS, throughput) are matched where possible. |
| **Networking**                       | VPC configurations are mapped to equivalent network isolation constructs. Load balancer types (internal vs. external) are preserved. Security group rules are mapped to cloud-specific firewall rules. |
| **High availability and resilience** | Multi-AZ deployments are mapped to equivalent availability zone configurations. Read replicas and standby instances are configured appropriately. Backup and retention policies are maintained.        |
| **Access control**                   | IAM roles and service accounts are created with equivalent permissions. Encryption settings (at-rest, in-transit) are preserved. Authentication mechanisms are adapted to target cloud patterns.       |

## Managed vs. unmanaged services

The service equivalents registry includes both **managed** and **unmanaged** service options. The choice depends on the target form factor:

### Managed services

When available in the target environment, Tensor9 uses cloud provider-managed versions of services (databases, caches, message queues). Managed services include built-in backups, monitoring, and updates handled by the cloud provider.

### Third-party services

Third-party managed services (e.g., MongoDB Atlas, Confluent Cloud) are available across all deployment environments, including private. These services are hosted externally and accessed over the network.

### Unmanaged services

For environments where cloud provider-managed services aren't available, Tensor9 can use unmanaged equivalents:

* Kubernetes operators (e.g., CloudNative PostgreSQL)
* Self-hosted open-source software (e.g., MinIO, Redis)
* Containerized versions running on the appliance

Unmanaged services require operational management (backups, updates, scaling) to be handled within the appliance.

<Note>
  If the customer's environment is Private Kubernetes, unmanaged service equivalents require dependencies (Kubernetes operators or Helm charts) to be installed in the cluster. See [Service dependencies](/form-factor/kubernetes#service-dependencies) for details on how dependency management works.
</Note>

## Single origin stack for multiple environments

Service equivalents enable you to maintain a single origin stack that deploys to multiple target environments. Changes to your origin stack propagate to all supported form factors during compilation without requiring separate codebases per cloud provider.

## Form factor and service availability

Not all services are available in all form factors. The [form factor](/fundamentals/key-concepts#form-factor) defines which managed services are available in the target environment.

For example:

* **AWS**: Full access to AWS managed services (RDS, S3, ElastiCache, etc.)
* **Google Cloud**: Full access to Google Cloud managed services (Cloud SQL, GCS, Memorystore, etc.)
* **Private Kubernetes**: Kubernetes-native services, operators, and third-party managed services (e.g., MongoDB Atlas)

When creating a form factor, you specify which services are available. During compilation, Tensor9 selects the appropriate equivalent from the available options.

## Unsupported AWS services

While Tensor9 supports many AWS services, some popular AWS services are not currently supported for cross-cloud deployment:

| AWS Service        | Service Category       | Recommended Alternative                                                                                                                                                    |
| ------------------ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **EC2**            | Compute (VMs)          | ECS Fargate, EKS, or Lambda                                                                                                                                                |
| **DynamoDB**       | NoSQL Database         | DocumentDB (MongoDB-compatible)                                                                                                                                            |
| **EFS**            | File Storage           | EBS volumes or S3 for object storage                                                                                                                                       |
| **SQS**            | Message Queue          | MSK (Kafka) or application-level queuing                                                                                                                                   |
| **SNS**            | Pub/Sub Messaging      | MSK (Kafka) or application-level pub/sub                                                                                                                                   |
| **Kinesis**        | Stream Processing      | MSK (Kafka)                                                                                                                                                                |
| **EventBridge**    | Event Bus              | MSK (Kafka) or application-level events                                                                                                                                    |
| **Step Functions** | Workflow Orchestration | MWAA (Managed Airflow)                                                                                                                                                     |
| **API Gateway**    | API Management         | ALB/NLB with application routing                                                                                                                                           |
| **Cognito**        | Authentication         | Application-level authentication                                                                                                                                           |
| **AppSync**        | GraphQL API            | Application-level GraphQL server                                                                                                                                           |
| **Redshift**       | Data Warehouse         | No cross-cloud equivalent. Use your target cloud's native analytical service (Athena on AWS, BigQuery on GCP, Synapse on Azure) with cloud-specific origin stack branches. |

If your origin stack uses these services, you'll need to refactor to use supported alternatives from the [service equivalents registry](#service-equivalents-registry).

<Note>
  If you need a service that isn't listed here or in the service equivalents registry, please contact [support@tensor9.com](mailto:support@tensor9.com) to discuss your requirements.
</Note>

## Limitations and considerations

<AccordionGroup>
  <Accordion title="Unsupported services">
    Some popular AWS services are not currently supported for cross-cloud deployment. See [**Unsupported AWS services**](#unsupported-aws-services) for the full list and recommended alternatives.
  </Accordion>

  <Accordion title="Provider-specific features">
    Some cloud-specific features may not have direct equivalents across all providers. For example:

    * Azure-specific features like Cosmos DB multi-model APIs
    * Google Cloud-specific services like BigQuery ML

    In these cases, you may need to:

    * Use a more generic service type that's available across clouds
    * Include conditional logic in your origin stack
    * Define form factor-specific overrides
  </Accordion>

  <Accordion title="Performance characteristics">
    While Tensor9 maps configuration semantically, exact performance characteristics may vary between clouds due to differences in:

    * Hardware specifications
    * Network architecture
    * Storage backend implementations

    Always test in a [test appliance](/fundamentals/appliances#test-appliances) for your target form factor.
  </Accordion>

  <Accordion title="Application code portability">
    Service equivalents are wire compatible, so your application code doesn't need to change when deploying across different cloud providers. Tensor9 handles endpoint injection and provides emulation layers where necessary (e.g., S3-compatible APIs for non-AWS object storage). Your application code uses standard client libraries that work the same across all clouds.
  </Accordion>

  <Accordion title="S3 API compatibility">
    When deploying to Azure appliances, Tensor9 provides S3-compatible API emulation for Azure Blob Storage. The emulation supports common S3 operations but has limitations compared to native AWS S3:

    **Supported S3 operations:**

    * `GetObject` - Download objects
    * `PutObject` - Upload objects
    * `DeleteObject` - Delete objects
    * `DeleteBucket` - Delete buckets
    * `DeleteObjectVersion` - Delete object versions
    * `ListObjects` / `ListObjectsV2` - List objects in a bucket
    * `ListBuckets` - List all buckets
    * `ListObjectVersions` - List object versions
    * `GetPresignedUrl` - Generate pre-signed URLs for temporary access

    **Unsupported operations:**
    Advanced S3 features like lifecycle policies, replication, and bucket policies are not supported in the Azure emulation layer.

    <Note>
      Google Cloud Storage and MinIO (used in private/on-prem deployments) provide native S3 compatibility and support a broader range of S3 operations beyond this list.
    </Note>
  </Accordion>

  <Accordion title="Resource naming">
    Some clouds have stricter naming requirements than others. Ensure your origin stack uses the `${var.instance_id}` suffix for resource names to maintain uniqueness, and avoid special characters that may not be supported in all clouds.
  </Accordion>
</AccordionGroup>

## Best practices

<AccordionGroup>
  <Accordion title="Check the service equivalents registry">
    The service equivalents registry defines which services can be mapped across form factors. If your origin stack uses a service not in the registry, that service cannot be mapped and you will need to use an alternative that is supported.
  </Accordion>

  <Accordion title="Test across form factors">
    Create test appliances for each form factor you intend to support. This validates that service equivalents work correctly for your specific use case.
  </Accordion>

  <Accordion title="Evaluate cross-cloud behavior">
    Evaluate how your application performs across different form factors using the [observability](/fundamentals/observability) feature.
  </Accordion>
</AccordionGroup>

## Related topics

* [**Deployments**](/fundamentals/deployments): Learn how compilation uses service equivalents
* [**Form factors**](/fundamentals/key-concepts#form-factor): Understand how form factors define available services
* [**Origin stacks**](/fundamentals/origin-stacks): Create portable infrastructure code
* [**Appliances**](/fundamentals/appliances): Deploy to different cloud environments
