The aws:appconfig/hostedConfigurationVersion:HostedConfigurationVersion resource, part of the Pulumi AWS provider, creates an immutable version of configuration data stored in AppConfig, whether freeform JSON or structured feature flags. This guide focuses on three capabilities: freeform JSON configuration, feature flag definitions with typed attributes, and multi-variant targeting rules.
Configuration versions belong to an AppConfig application and configuration profile that must exist first. The examples are intentionally small. Combine them with your own AppConfig application, configuration profile, and deployment strategy.
Store freeform JSON configuration data
Applications often need to version arbitrary configuration that doesn’t fit a predefined schema.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.appconfig.HostedConfigurationVersion("example", {
applicationId: exampleAwsAppconfigApplication.id,
configurationProfileId: exampleAwsAppconfigConfigurationProfile.configurationProfileId,
description: "Example Freeform Hosted Configuration Version",
contentType: "application/json",
content: JSON.stringify({
foo: "bar",
fruit: [
"apple",
"pear",
"orange",
],
isThingEnabled: true,
}),
});
import pulumi
import json
import pulumi_aws as aws
example = aws.appconfig.HostedConfigurationVersion("example",
application_id=example_aws_appconfig_application["id"],
configuration_profile_id=example_aws_appconfig_configuration_profile["configurationProfileId"],
description="Example Freeform Hosted Configuration Version",
content_type="application/json",
content=json.dumps({
"foo": "bar",
"fruit": [
"apple",
"pear",
"orange",
],
"isThingEnabled": True,
}))
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/appconfig"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
tmpJSON0, err := json.Marshal(map[string]interface{}{
"foo": "bar",
"fruit": []string{
"apple",
"pear",
"orange",
},
"isThingEnabled": true,
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = appconfig.NewHostedConfigurationVersion(ctx, "example", &appconfig.HostedConfigurationVersionArgs{
ApplicationId: pulumi.Any(exampleAwsAppconfigApplication.Id),
ConfigurationProfileId: pulumi.Any(exampleAwsAppconfigConfigurationProfile.ConfigurationProfileId),
Description: pulumi.String("Example Freeform Hosted Configuration Version"),
ContentType: pulumi.String("application/json"),
Content: pulumi.String(json0),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.AppConfig.HostedConfigurationVersion("example", new()
{
ApplicationId = exampleAwsAppconfigApplication.Id,
ConfigurationProfileId = exampleAwsAppconfigConfigurationProfile.ConfigurationProfileId,
Description = "Example Freeform Hosted Configuration Version",
ContentType = "application/json",
Content = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["foo"] = "bar",
["fruit"] = new[]
{
"apple",
"pear",
"orange",
},
["isThingEnabled"] = true,
}),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.appconfig.HostedConfigurationVersion;
import com.pulumi.aws.appconfig.HostedConfigurationVersionArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 example = new HostedConfigurationVersion("example", HostedConfigurationVersionArgs.builder()
.applicationId(exampleAwsAppconfigApplication.id())
.configurationProfileId(exampleAwsAppconfigConfigurationProfile.configurationProfileId())
.description("Example Freeform Hosted Configuration Version")
.contentType("application/json")
.content(serializeJson(
jsonObject(
jsonProperty("foo", "bar"),
jsonProperty("fruit", jsonArray(
"apple",
"pear",
"orange"
)),
jsonProperty("isThingEnabled", true)
)))
.build());
}
}
resources:
example:
type: aws:appconfig:HostedConfigurationVersion
properties:
applicationId: ${exampleAwsAppconfigApplication.id}
configurationProfileId: ${exampleAwsAppconfigConfigurationProfile.configurationProfileId}
description: Example Freeform Hosted Configuration Version
contentType: application/json
content:
fn::toJSON:
foo: bar
fruit:
- apple
- pear
- orange
isThingEnabled: true
The content property holds your JSON configuration as a string. The contentType specifies the MIME type; use “application/json” for JSON data. Each version is immutable once created, so changes require creating a new version.
Define feature flags with typed attributes
Feature flag systems need structured definitions with metadata and typed attributes.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.appconfig.HostedConfigurationVersion("example", {
applicationId: exampleAwsAppconfigApplication.id,
configurationProfileId: exampleAwsAppconfigConfigurationProfile.configurationProfileId,
description: "Example Feature Flag Configuration Version",
contentType: "application/json",
content: JSON.stringify({
flags: {
foo: {
name: "foo",
_deprecation: {
status: "planned",
},
},
bar: {
name: "bar",
attributes: {
someAttribute: {
constraints: {
type: "string",
required: true,
},
},
someOtherAttribute: {
constraints: {
type: "number",
required: true,
},
},
},
},
},
values: {
foo: {
enabled: "true",
},
bar: {
enabled: "true",
someAttribute: "Hello World",
someOtherAttribute: 123,
},
},
version: "1",
}),
});
import pulumi
import json
import pulumi_aws as aws
example = aws.appconfig.HostedConfigurationVersion("example",
application_id=example_aws_appconfig_application["id"],
configuration_profile_id=example_aws_appconfig_configuration_profile["configurationProfileId"],
description="Example Feature Flag Configuration Version",
content_type="application/json",
content=json.dumps({
"flags": {
"foo": {
"name": "foo",
"_deprecation": {
"status": "planned",
},
},
"bar": {
"name": "bar",
"attributes": {
"someAttribute": {
"constraints": {
"type": "string",
"required": True,
},
},
"someOtherAttribute": {
"constraints": {
"type": "number",
"required": True,
},
},
},
},
},
"values": {
"foo": {
"enabled": "true",
},
"bar": {
"enabled": "true",
"someAttribute": "Hello World",
"someOtherAttribute": 123,
},
},
"version": "1",
}))
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/appconfig"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
tmpJSON0, err := json.Marshal(map[string]interface{}{
"flags": map[string]interface{}{
"foo": map[string]interface{}{
"name": "foo",
"_deprecation": map[string]interface{}{
"status": "planned",
},
},
"bar": map[string]interface{}{
"name": "bar",
"attributes": map[string]interface{}{
"someAttribute": map[string]interface{}{
"constraints": map[string]interface{}{
"type": "string",
"required": true,
},
},
"someOtherAttribute": map[string]interface{}{
"constraints": map[string]interface{}{
"type": "number",
"required": true,
},
},
},
},
},
"values": map[string]interface{}{
"foo": map[string]interface{}{
"enabled": "true",
},
"bar": map[string]interface{}{
"enabled": "true",
"someAttribute": "Hello World",
"someOtherAttribute": 123,
},
},
"version": "1",
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = appconfig.NewHostedConfigurationVersion(ctx, "example", &appconfig.HostedConfigurationVersionArgs{
ApplicationId: pulumi.Any(exampleAwsAppconfigApplication.Id),
ConfigurationProfileId: pulumi.Any(exampleAwsAppconfigConfigurationProfile.ConfigurationProfileId),
Description: pulumi.String("Example Feature Flag Configuration Version"),
ContentType: pulumi.String("application/json"),
Content: pulumi.String(json0),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.AppConfig.HostedConfigurationVersion("example", new()
{
ApplicationId = exampleAwsAppconfigApplication.Id,
ConfigurationProfileId = exampleAwsAppconfigConfigurationProfile.ConfigurationProfileId,
Description = "Example Feature Flag Configuration Version",
ContentType = "application/json",
Content = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["flags"] = new Dictionary<string, object?>
{
["foo"] = new Dictionary<string, object?>
{
["name"] = "foo",
["_deprecation"] = new Dictionary<string, object?>
{
["status"] = "planned",
},
},
["bar"] = new Dictionary<string, object?>
{
["name"] = "bar",
["attributes"] = new Dictionary<string, object?>
{
["someAttribute"] = new Dictionary<string, object?>
{
["constraints"] = new Dictionary<string, object?>
{
["type"] = "string",
["required"] = true,
},
},
["someOtherAttribute"] = new Dictionary<string, object?>
{
["constraints"] = new Dictionary<string, object?>
{
["type"] = "number",
["required"] = true,
},
},
},
},
},
["values"] = new Dictionary<string, object?>
{
["foo"] = new Dictionary<string, object?>
{
["enabled"] = "true",
},
["bar"] = new Dictionary<string, object?>
{
["enabled"] = "true",
["someAttribute"] = "Hello World",
["someOtherAttribute"] = 123,
},
},
["version"] = "1",
}),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.appconfig.HostedConfigurationVersion;
import com.pulumi.aws.appconfig.HostedConfigurationVersionArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 example = new HostedConfigurationVersion("example", HostedConfigurationVersionArgs.builder()
.applicationId(exampleAwsAppconfigApplication.id())
.configurationProfileId(exampleAwsAppconfigConfigurationProfile.configurationProfileId())
.description("Example Feature Flag Configuration Version")
.contentType("application/json")
.content(serializeJson(
jsonObject(
jsonProperty("flags", jsonObject(
jsonProperty("foo", jsonObject(
jsonProperty("name", "foo"),
jsonProperty("_deprecation", jsonObject(
jsonProperty("status", "planned")
))
)),
jsonProperty("bar", jsonObject(
jsonProperty("name", "bar"),
jsonProperty("attributes", jsonObject(
jsonProperty("someAttribute", jsonObject(
jsonProperty("constraints", jsonObject(
jsonProperty("type", "string"),
jsonProperty("required", true)
))
)),
jsonProperty("someOtherAttribute", jsonObject(
jsonProperty("constraints", jsonObject(
jsonProperty("type", "number"),
jsonProperty("required", true)
))
))
))
))
)),
jsonProperty("values", jsonObject(
jsonProperty("foo", jsonObject(
jsonProperty("enabled", "true")
)),
jsonProperty("bar", jsonObject(
jsonProperty("enabled", "true"),
jsonProperty("someAttribute", "Hello World"),
jsonProperty("someOtherAttribute", 123)
))
)),
jsonProperty("version", "1")
)))
.build());
}
}
resources:
example:
type: aws:appconfig:HostedConfigurationVersion
properties:
applicationId: ${exampleAwsAppconfigApplication.id}
configurationProfileId: ${exampleAwsAppconfigConfigurationProfile.configurationProfileId}
description: Example Feature Flag Configuration Version
contentType: application/json
content:
fn::toJSON:
flags:
foo:
name: foo
_deprecation:
status: planned
bar:
name: bar
attributes:
someAttribute:
constraints:
type: string
required: true
someOtherAttribute:
constraints:
type: number
required: true
values:
foo:
enabled: 'true'
bar:
enabled: 'true'
someAttribute: Hello World
someOtherAttribute: 123
version: '1'
The flags section defines available flags with optional deprecation status. The values section sets each flag’s state and attribute values. The attributes block enforces type constraints; here, someAttribute must be a string and someOtherAttribute must be a number. The version field tracks the schema version.
Target feature flags to specific users
Advanced deployments enable flags conditionally based on user identity.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const example = new aws.appconfig.HostedConfigurationVersion("example", {
applicationId: exampleAwsAppconfigApplication.id,
configurationProfileId: exampleAwsAppconfigConfigurationProfile.configurationProfileId,
description: "Example Multi-variant Feature Flag Configuration Version",
contentType: "application/json",
content: JSON.stringify({
flags: {
loggingenabled: {
name: "loggingEnabled",
},
},
values: {
loggingenabled: {
_variants: std.concat({
input: [
.map(userId => ({
enabled: true,
name: `usersWithLoggingEnabled_${userId}`,
rule: `(or (eq $userId "${userId}"))`,
})),
[{
enabled: false,
name: "Default",
}],
],
}).then(invoke => invoke.result),
},
},
version: "1",
}),
});
import pulumi
import json
import pulumi_aws as aws
import pulumi_std as std
example = aws.appconfig.HostedConfigurationVersion("example",
application_id=example_aws_appconfig_application["id"],
configuration_profile_id=example_aws_appconfig_configuration_profile["configurationProfileId"],
description="Example Multi-variant Feature Flag Configuration Version",
content_type="application/json",
content=json.dumps({
"flags": {
"loggingenabled": {
"name": "loggingEnabled",
},
},
"values": {
"loggingenabled": {
"_variants": std.concat(input=[
[{
"enabled": True,
"name": f"usersWithLoggingEnabled_{user_id}",
"rule": f"(or (eq $userId \"{user_id}\"))",
} for userId in appcfg_enable_logging_user_ids],
[{
"enabled": False,
"name": "Default",
}],
]).result,
},
},
"version": "1",
}))
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var example = new Aws.AppConfig.HostedConfigurationVersion("example", new()
{
ApplicationId = exampleAwsAppconfigApplication.Id,
ConfigurationProfileId = exampleAwsAppconfigConfigurationProfile.ConfigurationProfileId,
Description = "Example Multi-variant Feature Flag Configuration Version",
ContentType = "application/json",
Content = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["flags"] = new Dictionary<string, object?>
{
["loggingenabled"] = new Dictionary<string, object?>
{
["name"] = "loggingEnabled",
},
},
["values"] = new Dictionary<string, object?>
{
["loggingenabled"] = new Dictionary<string, object?>
{
["_variants"] = Std.Concat.Invoke(new()
{
Input = new[]
{
.Select(userId =>
{
return
{
{ "enabled", true },
{ "name", $"usersWithLoggingEnabled_{userId}" },
{ "rule", $"(or (eq $userId \"{userId}\"))" },
};
}).ToList(),
new[]
{
{
{ "enabled", false },
{ "name", "Default" },
},
},
},
}).Apply(invoke => invoke.Result),
},
},
["version"] = "1",
}),
});
});
The _variants array defines multiple flag states with targeting rules. Each variant specifies whether the flag is enabled and a rule expression that determines when it applies. Rules use AppConfig’s expression syntax to match user attributes; here, flags enable for specific user IDs and default to disabled for everyone else.
Beyond these examples
These snippets focus on specific configuration version features: freeform JSON configuration, feature flag definitions with typed attributes, and multi-variant targeting rules. They’re intentionally minimal rather than full configuration management systems.
The examples reference pre-existing infrastructure such as AppConfig application (applicationId) and AppConfig configuration profile (configurationProfileId). They focus on versioning configuration data rather than provisioning the surrounding AppConfig resources.
To keep things focused, common configuration patterns are omitted, including:
- Description metadata (description property)
- Version number management (versionNumber is output-only)
- Content validation against profile validators
- Deployment strategies and rollout configuration
These omissions are intentional: the goal is to illustrate how each configuration format is structured, not provide drop-in configuration management modules. See the AppConfig HostedConfigurationVersion resource reference for all available configuration options.
Let's create AWS AppConfig Hosted Configuration Versions
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration Basics & Immutability
applicationId, configurationProfileId, content, contentType, description) are immutable. To update configuration data, create a new HostedConfigurationVersion resource.application/json for JSON-formatted configurations.Content Formats & Structure
content property. The freeform example demonstrates arbitrary key-value pairs, arrays, and boolean values.flags, values, and version keys to define toggleable features.Feature Flags
Structure your JSON content with three keys:
- flags - Define each flag with a name and optional attributes/constraints
- values - Set the enabled state and attribute values for each flag
- version - Specify the configuration version (e.g., “1”)
_variants array. Each variant includes an enabled state, name, and optional rule for conditional evaluation (e.g., user-based targeting).Using a different cloud?
Explore integration guides for other cloud providers: