Skip to content

Hosted SaaS

Hosted SaaS means your product runs in cloud accounts you own and operate. Customers get a managed service without provisioning cloud infrastructure or taking responsibility for upgrades, scaling, monitoring, and recovery. You retain ownership of the infrastructure and the customer experience; Omnistrate generates the control plane that automates provisioning, tenant management, operations, and monetization.

Hosted SaaS does not have to mean putting every customer into one shared application stack. You can offer the convenience of SaaS with a dedicated environment for each customer, or group customers into smaller shared cells to balance isolation and cost.

One Deployment Model, Multiple Customer Experiences

Customers can use a ready-to-use application, create and configure their own managed service instance, or run an AI agent with customer-specific data and tools. You decide how much configuration to expose, but in every case you host the service in your cloud accounts and remain responsible for provisioning, scaling, upgrades, and recovery. A customer who provisions a database or configures an agent is choosing how to use your service—not taking over infrastructure management.

Customer experience What customers do What you operate
Applications Sign in to a web application or call an API without managing deployments. The application, its backing services, tenant access, and runtime capacity.
Self-service platforms Provision and configure a managed database, analytics service, application runtime, or integration stack on demand. Customer-specific deployments, resource limits, endpoints, backups, and upgrades.
AI agents Invoke an agent or configure a workspace that executes multi-step workflows on their behalf. Agent runtimes, tool integrations, model endpoints, memory and vector stores, and execution boundaries.

All three experiences need repeatable onboarding, lifecycle management, observability, and billing. Customer self-service can expose application access, deployment configuration, or agent settings while keeping infrastructure operations under your control.

Choose the Right Tenant Isolation

Tenancy and deployment ownership are separate decisions. Hosted SaaS tells you where the product runs; tenancy tells you which resources customers share. Choose a boundary based on workload risk, performance requirements, regional placement, and the economics of each service plan.

Cellular Multi-Tenancy

Cellular multi-tenancy groups customer deployments into bounded shared environments. Instead of operating one large shared fleet as a single failure domain, you use cells to organize capacity, tenant placement, observability, and upgrade rollouts.

This is a good fit for cost-efficient plans and high customer density. Cells can separate customer groups by region, tier, workload, or capacity profile, and help limit the impact of failures and upgrades. Sharing resources within a cell still requires tenant-aware application behavior and appropriate access controls; a cell is not a dedicated environment for every customer.

See the Cellular Multi-Tenancy Overview and Deployment Guide.

Dedicated Tenancy (Single-Tenant SaaS)

Dedicated tenancy gives each customer deployment its own infrastructure stack while you continue to host and manage it as SaaS. This is useful when customers need predictable performance, stronger separation of data and workloads, or customer-specific configuration and lifecycle policies.

The isolation boundary must cover more than application compute. Evaluate databases, storage, networks, credentials, endpoints, and backups as well. With Omnistrate, dedicated tenancy provisions dedicated VMs and attached storage; you can extend the boundary with one deployment per cell and Customer Networks.

See the Dedicated Tenancy Overview and Deployment Guide.

Offer Both Through Service Plans

You do not need the same isolation level for every customer. A starter plan can use cellular multi-tenancy for efficient resource sharing, while an enterprise plan uses dedicated tenancy for stronger isolation. Both remain Hosted SaaS and use the same control-plane framework for onboarding, operations, and billing.

For Helm, Kustomize, Terraform, and OpenTofu deployments, define the required isolation in your deployment artifacts and use Custom Tenancy.

Why Isolation Matters for Enterprise SaaS

Enterprise requirements often go beyond a login and a shared application endpoint:

  • AI execution boundaries: Agents can retrieve sensitive context, invoke tools, and take actions across connected systems. Isolate customer state and credentials, scope tool permissions, and separate development, test, and production environments. Infrastructure isolation complements, rather than replaces, application-level authorization and sandboxing.
  • Regional placement and data residency: Place workloads where customers need them and account for where databases, logs, backups, and external integrations process data. An isolation model alone does not establish regulatory compliance.
  • Predictable performance: Dedicated resources can reduce contention between customers; cells help partition capacity and workload profiles.
  • Smaller operational blast radius: Use bounded cells, staged upgrades, health checks, and customer-specific operational policies so an incident or release does not have to affect the entire fleet.

The goal is to offer the right level of isolation without turning every enterprise customer into a manually operated deployment.

How Omnistrate Helps You Deliver Hosted SaaS

Define your application stack and service plans once, then use the generated control plane to manage the customer lifecycle:

  • Provisioning and infrastructure: Onboard your provider accounts and automate deployment of versioned application stacks. Start with Deployment Models.
  • Tenant access and self-service: Provide customer onboarding, subscriptions, deployment APIs, and a portal with the configuration options you choose to expose. See Tenant Management.
  • Application operations: Configure scaling, health checks, observability, backups, and recovery for your workload. See Runtime Management.
  • Fleet operations: Monitor deployments and manage upgrades across customers, regions, and service plans. See Fleet Management.
  • Monetization: Configure pricing, usage metering, and billing workflows for your product. See FinOps.

For AI products, include the agent runtime and its backing services in the same deployment definition. This keeps models, memory stores, vector databases, and tool integrations within the isolation boundary you design, rather than treating the agent as a standalone container with unmanaged dependencies.

PostgreSQL Hosted SaaS Example

This example builds a dedicated, provider-hosted PostgreSQL service, starting with a basic container and adding multi-cloud deployment, customer configuration, observability, read replicas, and operational capabilities. Customers request a database through your service; the underlying infrastructure remains in your cloud accounts.

Note

This walkthrough retains the PostgreSQL configuration from the original example and is illustrative, not a production-ready database deployment. Select and pin an available, tested container image; replace sample passwords and password defaults; and validate TLS, network access, backups, restore, and failover before launch. Review scaling policies per resource: scaling a PostgreSQL writer requires database-aware coordination, and read replicas alone do not provide automatic writer failover.

Basic PostgreSQL Service

Here's a simple PostgreSQL service definition:

version: '3.9'

services:
  PostgreSQL:
    image: bitnami/postgresql:latest
    ports:
      - 5432:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    environment:
      - POSTGRESQL_PASSWORD=defaultpassword
      - POSTGRESQL_DATABASE=postgres
      - POSTGRESQL_USERNAME=postgres
      - POSTGRESQL_POSTGRES_PASSWORD=your-secure-password

While this works, it lacks the enterprise features needed for a production Hosted SaaS offering. Let's enhance it step by step.

Step 1: Configure Cloud Provider Account

First, follow Account Onboarding to connect the provider accounts where you will host PostgreSQL. Configure hostedDeployment with the values from onboarding, keeping only the cloud providers you intend to support. Customers do not need to supply their own cloud accounts.

Hosted SaaS Deployment (Multi-Cloud)

x-omnistrate-service-plan:
  name: 'PostgreSQL Service'
  tenancyType: 'OMNISTRATE_DEDICATED_TENANCY'
  deployment:
    hostedDeployment:
      awsAccountId: "<AWS_ACCOUNT_ID>"
      awsBootstrapRoleAccountArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/omnistrate-bootstrap-role
      gcpProjectId: "<GCP_INFO>"
      gcpProjectNumber: "<GCP_INFO>"
      gcpServiceAccountEmail: "<GCP_INFO>"
      azureSubscriptionId: '<AZURE_INFO>'
      azureTenantId: '<AZURE_INFO>'

Step 2: Add Observability and Integrations

Enable comprehensive monitoring and logging:

x-customer-integrations:
  logs:
  metrics:

Step 3: Add Customer Customization

Allow customers to configure their PostgreSQL instances:

services:
  PostgreSQL:
    image: bitnami/postgresql:latest
    ports:
      - 5432:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    x-omnistrate-compute:
      instanceTypes:
        - cloudProvider: aws
          apiParam: instanceType
        - cloudProvider: gcp
          apiParam: instanceType
        - cloudProvider: azure
          apiParam: instanceType
    x-omnistrate-storage:
      aws:
        instanceStorageType: AWS::EBS_GP3
        instanceStorageSizeGiAPIParam: storageSize
        instanceStorageIOPSAPIParam: storageIOPS
      gcp:
        instanceStorageType: GCP::PD_SSD
        instanceStorageSizeGiAPIParam: storageSize
      azure:
        instanceStorageType: AZURE::PREMIUM_LRS
        instanceStorageSizeGiAPIParam: storageSize
    environment:
      - POSTGRESQL_PASSWORD=$var.postgresqlPassword
      - POSTGRESQL_DATABASE=$var.postgresqlDatabase
      - POSTGRESQL_USERNAME=$var.postgresqlUsername
      - POSTGRESQL_POSTGRES_PASSWORD=$var.postgresqlRootPassword
      - POSTGRESQL_PGAUDIT_LOG=READ,WRITE
      - POSTGRESQL_LOG_HOSTNAME=true
    x-omnistrate-api-params:
      - key: instanceType
        description: Instance Type for PostgreSQL
        name: Instance Type
        type: String
        modifiable: true
        required: true
        export: true
      - key: storageSize
        description: Storage Size in GB
        name: Storage Size (GB)
        type: Float64
        modifiable: true
        required: true
        export: true
        defaultValue: "100"
        limits:
          min: 20
          max: 1000
      - key: storageIOPS
        description: Storage IOPS
        name: Storage IOPS
        type: Float64
        modifiable: true
        required: false
        export: true
        defaultValue: "3000"
      - key: postgresqlUsername
        description: Database Username
        name: Database Username
        type: String
        modifiable: false
        required: true
        export: true
      - key: postgresqlPassword
        description: Database Password
        name: Database Password
        type: String
        modifiable: false
        required: true
        export: false
      - key: postgresqlDatabase
        description: Database Name
        name: Database Name
        type: String
        modifiable: false
        required: true
        export: true
        defaultValue: "postgres"
      - key: postgresqlRootPassword
        description: Root Password
        name: Root Password
        type: String
        modifiable: false
        required: false
        export: false
        defaultValue: "generate-secure-password"

Step 4: Add Read Replicas and Multi-Zone Placement

Add a primary and configurable read replicas. Replication and multi-zone placement are building blocks for availability; validate database failover and recovery separately:

services:
  Master:
    image: bitnami/postgresql:latest
    ports:
      - 5432:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    x-omnistrate-compute:
      instanceTypes:
        - cloudProvider: aws
          apiParam: masterInstanceType
        - cloudProvider: gcp
          apiParam: masterInstanceType
        - cloudProvider: azure
          apiParam: masterInstanceType
    x-omnistrate-capabilities:
      enableEndpointPerReplica: true
      enableMultiZone: true
    environment:
      - POSTGRESQL_PASSWORD=$var.postgresqlPassword
      - POSTGRESQL_DATABASE=$var.postgresqlDatabase
      - POSTGRESQL_USERNAME=$var.postgresqlUsername
      - POSTGRESQL_POSTGRES_PASSWORD=$var.postgresqlRootPassword
      - POSTGRESQL_REPLICATION_MODE=master
      - POSTGRESQL_REPLICATION_USER=repl_user
      - POSTGRESQL_REPLICATION_PASSWORD=$var.replicationPassword
      - POSTGRESQL_PGAUDIT_LOG=READ,WRITE
      - POSTGRESQL_LOG_HOSTNAME=true
    x-omnistrate-api-params:
      - key: masterInstanceType
        description: Master Instance Type
        name: Master Instance Type
        type: String
        modifiable: true
        required: true
        export: true
      - key: postgresqlUsername
        description: Database Username
        name: Database Username
        type: String
        modifiable: false
        required: true
        export: true
      - key: postgresqlPassword
        description: Database Password
        name: Database Password
        type: String
        modifiable: false
        required: true
        export: false
      - key: postgresqlDatabase
        description: Database Name
        name: Database Name
        type: String
        modifiable: false
        required: true
        export: true
      - key: postgresqlRootPassword
        description: Root Password
        name: Root Password
        type: String
        modifiable: false
        required: false
        export: false
        defaultValue: "rootpassword123"
      - key: replicationPassword
        description: Replication Password
        name: Replication Password
        type: String
        modifiable: false
        required: false
        export: false

  Replica:
    image: bitnami/postgresql:latest
    ports:
      - 5433:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    x-omnistrate-compute:
      replicaCountAPIParam: numReadReplicas
      instanceTypes:
        - cloudProvider: aws
          apiParam: replicaInstanceType
        - cloudProvider: gcp
          apiParam: replicaInstanceType
        - cloudProvider: azure
          apiParam: replicaInstanceType
    x-omnistrate-capabilities:
      enableMultiZone: true
      enableEndpointPerReplica: true
    environment:
      - POSTGRESQL_PASSWORD=$var.postgresqlPassword
      - POSTGRESQL_MASTER_HOST=Master
      - POSTGRESQL_MASTER_PORT_NUMBER=5432
      - POSTGRESQL_REPLICATION_MODE=slave
      - POSTGRESQL_REPLICATION_USER=repl_user
      - POSTGRESQL_REPLICATION_PASSWORD=$var.replicationPassword
      - POSTGRESQL_PGAUDIT_LOG=READ,WRITE
      - POSTGRESQL_LOG_HOSTNAME=true
    x-omnistrate-api-params:
      - key: replicaInstanceType
        description: Replica Instance Type
        name: Replica Instance Type
        type: String
        modifiable: true
        required: true
        export: true
      - key: numReadReplicas
        description: Number of Read Replicas
        name: Number of Read Replicas
        type: Float64
        modifiable: true
        required: false
        export: true
        defaultValue: "1"
        limits:
          min: 0
          max: 5
      - key: postgresqlPassword
        description: Database Password
        name: Database Password
        type: String
        modifiable: false
        required: true
        export: false
      - key: replicationPassword
        description: Replication Password
        name: Replication Password
        type: String
        modifiable: false
        required: false
        export: false
        defaultValue: "replpassword123"

Step 5: Add Enterprise Features

Enable autoscaling, backup, and advanced capabilities:

x-omnistrate-capabilities:
  enableMultiZone: true
  enableEndpointPerReplica: true
  autoscaling:
    minReplicas: 1
    maxReplicas: 10
    idleMinutesBeforeScalingDown: 5
    idleThreshold: 20
    overUtilizedMinutesBeforeScalingUp: 2
    overUtilizedThreshold: 80
  backupConfiguration:
    backupRetentionInDays: 7
    backupPeriodInHours: 2

Complete PostgreSQL Hosted SaaS Example

The following combines the preceding configuration into one Compose specification. Save it as omnistrate-compose.yaml and adapt it to your provider accounts and database operating requirements:

version: '3.9'

x-omnistrate-service-plan:
  name: 'PostgreSQL Service'
  tenancyType: 'OMNISTRATE_DEDICATED_TENANCY'
  deployment:
    hostedDeployment:
      awsAccountId: "<AWS_ACCOUNT_ID>"
      awsBootstrapRoleAccountArn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/omnistrate-bootstrap-role
      gcpProjectId: "<GCP_INFO>"
      gcpProjectNumber: "<GCP_INFO>"
      gcpServiceAccountEmail: "<GCP_INFO>"
      azureSubscriptionId: '<AZURE_INFO>'
      azureTenantId: '<AZURE_INFO>'

x-customer-integrations:
  logs:
  metrics:

services:
  Master:
    image: bitnami/postgresql:latest
    ports:
      - 5432:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    x-omnistrate-compute:
      instanceTypes:
        - cloudProvider: aws
          apiParam: masterInstanceType
        - cloudProvider: gcp
          apiParam: masterInstanceType
        - cloudProvider: azure
          apiParam: masterInstanceType
    x-omnistrate-storage:
      aws:
        instanceStorageType: AWS::EBS_GP3
        instanceStorageSizeGiAPIParam: storageSize
        instanceStorageIOPSAPIParam: storageIOPS
      gcp:
        instanceStorageType: GCP::PD_SSD
        instanceStorageSizeGiAPIParam: storageSize
      azure:
        instanceStorageType: AZURE::PREMIUM_LRS
        instanceStorageSizeGiAPIParam: storageSize
    x-omnistrate-capabilities:
      enableEndpointPerReplica: true
      enableMultiZone: true
      autoscaling:
        minReplicas: 1
        maxReplicas: 3
        idleMinutesBeforeScalingDown: 5
        idleThreshold: 20
        overUtilizedMinutesBeforeScalingUp: 2
        overUtilizedThreshold: 80
    environment:
      - POSTGRESQL_PASSWORD=$var.postgresqlPassword
      - POSTGRESQL_DATABASE=$var.postgresqlDatabase
      - POSTGRESQL_USERNAME=$var.postgresqlUsername
      - POSTGRESQL_POSTGRES_PASSWORD=$var.postgresqlRootPassword
      - POSTGRESQL_REPLICATION_MODE=master
      - POSTGRESQL_REPLICATION_USER=repl_user
      - POSTGRESQL_REPLICATION_PASSWORD=$var.replicationPassword
      - POSTGRESQL_PGAUDIT_LOG=READ,WRITE
      - POSTGRESQL_LOG_HOSTNAME=true
      - POSTGRESQL_DATA_DIR=/var/lib/postgresql/data/dbdata
      - SECURITY_CONTEXT_USER_ID=1001
      - SECURITY_CONTEXT_FS_GROUP=1001
      - SECURITY_CONTEXT_GROUP_ID=0
    x-omnistrate-api-params:
      - key: masterInstanceType
        description: Master Instance Type
        name: Master Instance Type
        type: String
        modifiable: true
        required: true
        export: true
      - key: storageSize
        description: Storage Size in GB
        name: Storage Size (GB)
        type: Float64
        modifiable: true
        required: true
        export: true
        defaultValue: "100"
        limits:
          min: 20
          max: 1000
      - key: storageIOPS
        description: Storage IOPS
        name: Storage IOPS
        type: Float64
        modifiable: true
        required: false
        export: true
        defaultValue: "3000"
      - key: postgresqlUsername
        description: Database Username
        name: Database Username
        type: String
        modifiable: false
        required: true
        export: true
      - key: postgresqlPassword
        description: Database Password
        name: Database Password
        type: String
        modifiable: false
        required: true
        export: false
      - key: postgresqlDatabase
        description: Database Name
        name: Database Name
        type: String
        modifiable: false
        required: true
        export: true
        defaultValue: "postgres"
      - key: postgresqlRootPassword
        description: Root Password
        name: Root Password
        type: String
        modifiable: false
        required: false
        export: false
        defaultValue: "CHANGEME_SECURE_PASSWORD"
      - key: replicationPassword
        description: Replication Password
        name: Replication Password
        type: String
        modifiable: false
        required: false
        export: false
        defaultValue: "CHANGEME_SECURE_PASSWORD"
    x-omnistrate-mode-internal: true

  Replica:
    image: bitnami/postgresql:latest
    ports:
      - 5433:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    x-omnistrate-compute:
      replicaCountAPIParam: numReadReplicas
      instanceTypes:
        - cloudProvider: aws
          apiParam: replicaInstanceType
        - cloudProvider: gcp
          apiParam: replicaInstanceType
        - cloudProvider: azure
          apiParam: replicaInstanceType
    x-omnistrate-capabilities:
      enableMultiZone: true
      enableEndpointPerReplica: true
    environment:
      - POSTGRESQL_PASSWORD=$var.postgresqlPassword
      - POSTGRESQL_MASTER_HOST=Master
      - POSTGRESQL_MASTER_PORT_NUMBER=5432
      - POSTGRESQL_REPLICATION_MODE=slave
      - POSTGRESQL_REPLICATION_USER=repl_user
      - POSTGRESQL_REPLICATION_PASSWORD=$var.replicationPassword
      - POSTGRESQL_PGAUDIT_LOG=READ,WRITE
      - POSTGRESQL_LOG_HOSTNAME=true
      - POSTGRESQL_DATA_DIR=/var/lib/postgresql/data/dbdata
      - SECURITY_CONTEXT_USER_ID=1001
      - SECURITY_CONTEXT_FS_GROUP=1001
      - SECURITY_CONTEXT_GROUP_ID=0
    x-omnistrate-api-params:
      - key: replicaInstanceType
        description: Replica Instance Type
        name: Replica Instance Type
        type: String
        modifiable: true
        required: true
        export: true
      - key: numReadReplicas
        description: Number of Read Replicas
        name: Number of Read Replicas
        type: Float64
        modifiable: true
        required: false
        export: true
        defaultValue: "1"
        limits:
          min: 0
          max: 5
      - key: postgresqlPassword
        description: Database Password
        name: Database Password
        type: String
        modifiable: false
        required: true
        export: false
      - key: replicationPassword
        description: Replication Password
        name: Replication Password
        type: String
        modifiable: false
        required: false
        export: false
        defaultValue: "CHANGEME_SECURE_PASSWORD"
    x-omnistrate-mode-internal: true

  Cluster:
    image: omnistrate/noop
    x-omnistrate-api-params:
      - key: instanceType
        description: Instance Type
        name: Instance Type
        type: String
        modifiable: true
        required: true
        export: true
        parameterDependencyMap:
          Master: masterInstanceType
          Replica: replicaInstanceType
      - key: postgresqlPassword
        description: Database Password
        name: Database Password
        type: String
        modifiable: false
        required: true
        export: false
        parameterDependencyMap:
          Master: postgresqlPassword
          Replica: postgresqlPassword
      - key: postgresqlUsername
        description: Database Username
        name: Database Username
        type: String
        modifiable: false
        required: true
        export: true
        parameterDependencyMap:
          Master: postgresqlUsername
      - key: postgresqlDatabase
        description: Database Name
        name: Database Name
        type: String
        modifiable: false
        required: true
        export: true
        defaultValue: "postgres"
        parameterDependencyMap:
          Master: postgresqlDatabase
      - key: numReadReplicas
        description: Number of Read Replicas
        name: Number of Read Replicas
        type: Float64
        modifiable: true
        required: false
        export: true
        defaultValue: "1"
        limits:
          min: 0
          max: 5
        parameterDependencyMap:
          Replica: numReadReplicas
      - key: storageSize
        description: Storage Size in GB
        name: Storage Size (GB)
        type: Float64
        modifiable: true
        required: true
        export: true
        defaultValue: "100"
        limits:
          min: 20
          max: 1000
        parameterDependencyMap:
          Master: storageSize
    depends_on:
      - Master
      - Replica
    x-omnistrate-mode-internal: false

Build and Test the Service

Follow CLI Setup, then build the product from the complete specification:

omnistrate-ctl build --file omnistrate-compose.yaml --product-name "Hosted PostgreSQL" --description "Dedicated provider-hosted PostgreSQL service"

Use the generated Customer Portal to create a subscription and provision a test deployment. Supply the database credentials, instance type, storage settings, and replica count, then check connectivity, replication, monitoring, and your recovery workflows before launch.

For additional PostgreSQL implementations using Compose, Helm, and Kubernetes operators, see the Omnistrate Community PostgreSQL repository.

Further Reading