Create AWS Mainframe Modernization Environments

The aws:m2/environment:Environment resource, part of the Pulumi AWS provider, provisions AWS Mainframe Modernization runtime environments that host modernized mainframe applications. This guide focuses on three capabilities: engine and compute configuration, high availability setup, and EFS and FSx storage attachment.

Environments run in VPCs and reference existing security groups, subnets, and optionally EFS or FSx filesystems. The examples are intentionally small. Combine them with your own VPC infrastructure and storage resources.

Create a runtime environment with network placement

Mainframe Modernization environments host modernized mainframe applications in AWS, requiring an engine type, compute capacity, and VPC placement.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const test = new aws.m2.Environment("test", {
    name: "test-env",
    engineType: "bluage",
    instanceType: "M2.m5.large",
    securityGroups: ["sg-01234567890abcdef"],
    subnetIds: [
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
});
import pulumi
import pulumi_aws as aws

test = aws.m2.Environment("test",
    name="test-env",
    engine_type="bluage",
    instance_type="M2.m5.large",
    security_groups=["sg-01234567890abcdef"],
    subnet_ids=[
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/m2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := m2.NewEnvironment(ctx, "test", &m2.EnvironmentArgs{
			Name:         pulumi.String("test-env"),
			EngineType:   pulumi.String("bluage"),
			InstanceType: pulumi.String("M2.m5.large"),
			SecurityGroups: []string{
				"sg-01234567890abcdef",
			},
			SubnetIds: pulumi.StringArray{
				pulumi.String("subnet-01234567890abcdef"),
				pulumi.String("subnet-01234567890abcdea"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var test = new Aws.M2.Environment("test", new()
    {
        Name = "test-env",
        EngineType = "bluage",
        InstanceType = "M2.m5.large",
        SecurityGroups = new[]
        {
            "sg-01234567890abcdef",
        },
        SubnetIds = new[]
        {
            "subnet-01234567890abcdef",
            "subnet-01234567890abcdea",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.m2.Environment;
import com.pulumi.aws.m2.EnvironmentArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var test = new Environment("test", EnvironmentArgs.builder()
            .name("test-env")
            .engineType("bluage")
            .instanceType("M2.m5.large")
            .securityGroups(List.of("sg-01234567890abcdef"))
            .subnetIds(            
                "subnet-01234567890abcdef",
                "subnet-01234567890abcdea")
            .build());

    }
}
resources:
  test:
    type: aws:m2:Environment
    properties:
      name: test-env
      engineType: bluage
      instanceType: M2.m5.large
      securityGroups:
        - sg-01234567890abcdef
      subnetIds:
        - subnet-01234567890abcdef
        - subnet-01234567890abcdea

The engineType property selects the modernization engine (bluage or microfocus), which determines how your mainframe code runs. The instanceType sets compute capacity. The securityGroups and subnetIds properties place the environment in your VPC, controlling network access to the hosted applications.

Configure high availability with multiple instances

Production workloads often require redundancy to handle instance failures without downtime.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const test = new aws.m2.Environment("test", {
    name: "test-env",
    engineType: "bluage",
    instanceType: "M2.m5.large",
    securityGroups: ["sg-01234567890abcdef"],
    subnetIds: [
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
    highAvailabilityConfig: {
        desiredCapacity: 2,
    },
});
import pulumi
import pulumi_aws as aws

test = aws.m2.Environment("test",
    name="test-env",
    engine_type="bluage",
    instance_type="M2.m5.large",
    security_groups=["sg-01234567890abcdef"],
    subnet_ids=[
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
    high_availability_config={
        "desired_capacity": 2,
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/m2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := m2.NewEnvironment(ctx, "test", &m2.EnvironmentArgs{
			Name:         pulumi.String("test-env"),
			EngineType:   pulumi.String("bluage"),
			InstanceType: pulumi.String("M2.m5.large"),
			SecurityGroups: []string{
				"sg-01234567890abcdef",
			},
			SubnetIds: pulumi.StringArray{
				pulumi.String("subnet-01234567890abcdef"),
				pulumi.String("subnet-01234567890abcdea"),
			},
			HighAvailabilityConfig: &m2.EnvironmentHighAvailabilityConfigArgs{
				DesiredCapacity: pulumi.Int(2),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var test = new Aws.M2.Environment("test", new()
    {
        Name = "test-env",
        EngineType = "bluage",
        InstanceType = "M2.m5.large",
        SecurityGroups = new[]
        {
            "sg-01234567890abcdef",
        },
        SubnetIds = new[]
        {
            "subnet-01234567890abcdef",
            "subnet-01234567890abcdea",
        },
        HighAvailabilityConfig = new Aws.M2.Inputs.EnvironmentHighAvailabilityConfigArgs
        {
            DesiredCapacity = 2,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.m2.Environment;
import com.pulumi.aws.m2.EnvironmentArgs;
import com.pulumi.aws.m2.inputs.EnvironmentHighAvailabilityConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var test = new Environment("test", EnvironmentArgs.builder()
            .name("test-env")
            .engineType("bluage")
            .instanceType("M2.m5.large")
            .securityGroups(List.of("sg-01234567890abcdef"))
            .subnetIds(            
                "subnet-01234567890abcdef",
                "subnet-01234567890abcdea")
            .highAvailabilityConfig(EnvironmentHighAvailabilityConfigArgs.builder()
                .desiredCapacity(2)
                .build())
            .build());

    }
}
resources:
  test:
    type: aws:m2:Environment
    properties:
      name: test-env
      engineType: bluage
      instanceType: M2.m5.large
      securityGroups:
        - sg-01234567890abcdef
      subnetIds:
        - subnet-01234567890abcdef
        - subnet-01234567890abcdea
      highAvailabilityConfig:
        desiredCapacity: 2

The highAvailabilityConfig property enables multi-instance deployment. The desiredCapacity sets how many instances run simultaneously, spreading capacity across the availability zones represented by your subnet list. AWS manages instance health and replacement automatically.

Attach EFS storage for shared application data

Applications that need shared file storage across instances can mount EFS filesystems for persistent data.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const test = new aws.m2.Environment("test", {
    name: "test-env",
    engineType: "bluage",
    instanceType: "M2.m5.large",
    securityGroups: ["sg-01234567890abcdef"],
    subnetIds: [
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
    storageConfiguration: {
        efs: {
            fileSystemId: "fs-01234567890abcdef",
            mountPoint: "/m2/mount/example",
        },
    },
});
import pulumi
import pulumi_aws as aws

test = aws.m2.Environment("test",
    name="test-env",
    engine_type="bluage",
    instance_type="M2.m5.large",
    security_groups=["sg-01234567890abcdef"],
    subnet_ids=[
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
    storage_configuration={
        "efs": {
            "file_system_id": "fs-01234567890abcdef",
            "mount_point": "/m2/mount/example",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/m2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := m2.NewEnvironment(ctx, "test", &m2.EnvironmentArgs{
			Name:         pulumi.String("test-env"),
			EngineType:   pulumi.String("bluage"),
			InstanceType: pulumi.String("M2.m5.large"),
			SecurityGroups: []string{
				"sg-01234567890abcdef",
			},
			SubnetIds: pulumi.StringArray{
				pulumi.String("subnet-01234567890abcdef"),
				pulumi.String("subnet-01234567890abcdea"),
			},
			StorageConfiguration: &m2.EnvironmentStorageConfigurationArgs{
				Efs: &m2.EnvironmentStorageConfigurationEfsArgs{
					FileSystemId: pulumi.String("fs-01234567890abcdef"),
					MountPoint:   pulumi.String("/m2/mount/example"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var test = new Aws.M2.Environment("test", new()
    {
        Name = "test-env",
        EngineType = "bluage",
        InstanceType = "M2.m5.large",
        SecurityGroups = new[]
        {
            "sg-01234567890abcdef",
        },
        SubnetIds = new[]
        {
            "subnet-01234567890abcdef",
            "subnet-01234567890abcdea",
        },
        StorageConfiguration = new Aws.M2.Inputs.EnvironmentStorageConfigurationArgs
        {
            Efs = new Aws.M2.Inputs.EnvironmentStorageConfigurationEfsArgs
            {
                FileSystemId = "fs-01234567890abcdef",
                MountPoint = "/m2/mount/example",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.m2.Environment;
import com.pulumi.aws.m2.EnvironmentArgs;
import com.pulumi.aws.m2.inputs.EnvironmentStorageConfigurationArgs;
import com.pulumi.aws.m2.inputs.EnvironmentStorageConfigurationEfsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var test = new Environment("test", EnvironmentArgs.builder()
            .name("test-env")
            .engineType("bluage")
            .instanceType("M2.m5.large")
            .securityGroups(List.of("sg-01234567890abcdef"))
            .subnetIds(            
                "subnet-01234567890abcdef",
                "subnet-01234567890abcdea")
            .storageConfiguration(EnvironmentStorageConfigurationArgs.builder()
                .efs(EnvironmentStorageConfigurationEfsArgs.builder()
                    .fileSystemId("fs-01234567890abcdef")
                    .mountPoint("/m2/mount/example")
                    .build())
                .build())
            .build());

    }
}
resources:
  test:
    type: aws:m2:Environment
    properties:
      name: test-env
      engineType: bluage
      instanceType: M2.m5.large
      securityGroups:
        - sg-01234567890abcdef
      subnetIds:
        - subnet-01234567890abcdef
        - subnet-01234567890abcdea
      storageConfiguration:
        efs:
          fileSystemId: fs-01234567890abcdef
          mountPoint: /m2/mount/example

The storageConfiguration property attaches external storage. The efs block specifies the filesystem ID and mount point where it appears inside environment instances. All instances in the environment access the same filesystem, enabling shared application state.

Attach FSx storage for Windows-compatible filesystems

Some mainframe applications require Windows-compatible file semantics or SMB protocol support.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const test = new aws.m2.Environment("test", {
    name: "test-env",
    engineType: "bluage",
    instanceType: "M2.m5.large",
    securityGroups: ["sg-01234567890abcdef"],
    subnetIds: [
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
    storageConfiguration: {
        fsx: {
            fileSystemId: "fs-01234567890abcdef",
            mountPoint: "/m2/mount/example",
        },
    },
});
import pulumi
import pulumi_aws as aws

test = aws.m2.Environment("test",
    name="test-env",
    engine_type="bluage",
    instance_type="M2.m5.large",
    security_groups=["sg-01234567890abcdef"],
    subnet_ids=[
        "subnet-01234567890abcdef",
        "subnet-01234567890abcdea",
    ],
    storage_configuration={
        "fsx": {
            "file_system_id": "fs-01234567890abcdef",
            "mount_point": "/m2/mount/example",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/m2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := m2.NewEnvironment(ctx, "test", &m2.EnvironmentArgs{
			Name:         pulumi.String("test-env"),
			EngineType:   pulumi.String("bluage"),
			InstanceType: pulumi.String("M2.m5.large"),
			SecurityGroups: []string{
				"sg-01234567890abcdef",
			},
			SubnetIds: pulumi.StringArray{
				pulumi.String("subnet-01234567890abcdef"),
				pulumi.String("subnet-01234567890abcdea"),
			},
			StorageConfiguration: &m2.EnvironmentStorageConfigurationArgs{
				Fsx: &m2.EnvironmentStorageConfigurationFsxArgs{
					FileSystemId: pulumi.String("fs-01234567890abcdef"),
					MountPoint:   pulumi.String("/m2/mount/example"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var test = new Aws.M2.Environment("test", new()
    {
        Name = "test-env",
        EngineType = "bluage",
        InstanceType = "M2.m5.large",
        SecurityGroups = new[]
        {
            "sg-01234567890abcdef",
        },
        SubnetIds = new[]
        {
            "subnet-01234567890abcdef",
            "subnet-01234567890abcdea",
        },
        StorageConfiguration = new Aws.M2.Inputs.EnvironmentStorageConfigurationArgs
        {
            Fsx = new Aws.M2.Inputs.EnvironmentStorageConfigurationFsxArgs
            {
                FileSystemId = "fs-01234567890abcdef",
                MountPoint = "/m2/mount/example",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.m2.Environment;
import com.pulumi.aws.m2.EnvironmentArgs;
import com.pulumi.aws.m2.inputs.EnvironmentStorageConfigurationArgs;
import com.pulumi.aws.m2.inputs.EnvironmentStorageConfigurationFsxArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var test = new Environment("test", EnvironmentArgs.builder()
            .name("test-env")
            .engineType("bluage")
            .instanceType("M2.m5.large")
            .securityGroups(List.of("sg-01234567890abcdef"))
            .subnetIds(            
                "subnet-01234567890abcdef",
                "subnet-01234567890abcdea")
            .storageConfiguration(EnvironmentStorageConfigurationArgs.builder()
                .fsx(EnvironmentStorageConfigurationFsxArgs.builder()
                    .fileSystemId("fs-01234567890abcdef")
                    .mountPoint("/m2/mount/example")
                    .build())
                .build())
            .build());

    }
}
resources:
  test:
    type: aws:m2:Environment
    properties:
      name: test-env
      engineType: bluage
      instanceType: M2.m5.large
      securityGroups:
        - sg-01234567890abcdef
      subnetIds:
        - subnet-01234567890abcdef
        - subnet-01234567890abcdea
      storageConfiguration:
        fsx:
          fileSystemId: fs-01234567890abcdef
          mountPoint: /m2/mount/example

The fsx block provides an alternative to EFS, using FSx for Windows File Server. Like EFS, you specify the filesystem ID and mount point. FSx provides Windows-compatible features like Active Directory integration and SMB protocol support.

Beyond these examples

These snippets focus on specific environment-level features: engine selection and compute sizing, high availability configuration, and EFS and FSx storage attachment. They’re intentionally minimal rather than full mainframe modernization deployments.

The examples reference pre-existing infrastructure such as VPC subnets and security groups, and EFS or FSx filesystems for storage examples. They focus on configuring the environment rather than provisioning the surrounding infrastructure.

To keep things focused, common environment patterns are omitted, including:

  • KMS encryption (kmsKeyId)
  • Maintenance windows (preferredMaintenanceWindow)
  • Public accessibility controls (publiclyAccessible)
  • Force update behavior (forceUpdate)

These omissions are intentional: the goal is to illustrate how each environment feature is wired, not provide drop-in modernization modules. See the Mainframe Modernization Environment resource reference for all available configuration options.

Let's create AWS Mainframe Modernization Environments

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Engine & Instance Configuration
What engine types are supported for M2 environments?
M2 environments support two engine types: microfocus and bluage.
High Availability
How do I enable high availability for my M2 environment?
Configure highAvailabilityConfig with desiredCapacity set to your desired number of instances (the example shows desiredCapacity: 2).
Storage Configuration
What storage options can I use with M2 environments?
You can attach either EFS or FSX filesystems using storageConfiguration. Both require a fileSystemId and mountPoint.
Networking & Security
How do I make applications in my environment publicly accessible?
Set publiclyAccessible to true to allow applications deployed to the environment to be publicly accessible.
Maintenance & Updates
What's the required format for maintenance windows?
Maintenance windows must use the format ddd:hh24:mi-ddd:hh24:mi (e.g., sun:05:00-sun:09:00) and must be less than 24 hours in duration.
What happens if I don't specify a maintenance window?
A random maintenance window value will be automatically assigned if you don’t provide one.
Can I update the environment while applications are running?
Yes, set forceUpdate to true to force an update even if applications are currently running.
Naming & Constraints
Does the environment name need to be unique?
Yes, the environment name must be unique within your AWS account.

Using a different cloud?

Explore compute guides for other cloud providers: