Skip to content

AWS Partitions

Floci serves every AWS partition, not only the commercial one. A partition is the second segment of every ARN (arn:aws-cn:...), the DNS suffix of every endpoint (amazonaws.com.cn), and the set of services and regions AWS publishes there. Floci reads all of it from AWS's own partition metadata (botocore's partitions.json and endpoints.json, vendored as aws/partitions.json and refreshed with make aws-data-sync, which also regenerates the AWS managed-policy catalog).

Partition DNS suffix Regions Example
aws amazonaws.com 34 published (17 opt-in) us-east-1
aws-cn amazonaws.com.cn cn-north-1, cn-northwest-1 cn-north-1
aws-us-gov amazonaws.com us-gov-east-1, us-gov-west-1 us-gov-west-1
aws-iso c2s.ic.gov us-iso-east-1, us-iso-west-1 us-iso-east-1
aws-iso-b sc2s.sgov.gov us-isob-east-1, us-isob-west-1 us-isob-east-1
aws-iso-e cloud.adc-e.uk eu-isoe-west-1 eu-isoe-west-1
aws-iso-f csp.hci.ic.gov us-isof-east-1, us-isof-south-1 us-isof-south-1
aws-eusc amazonaws.eu eusc-de-east-1 eusc-de-east-1

Which partition a deployment serves

The deployment's partition is derived from FLOCI_DEFAULT_REGION: cn-north-1 means aws-cn, us-gov-west-1 means aws-us-gov, and so on. Set FLOCI_PARTITIONS_ID (floci.partitions.id) to name it explicitly; startup refuses a value that is not a published partition or that contradicts a recognised default region, and logs one line naming the partition it settled on:

Partition: aws-cn (default-region cn-north-1, dns suffix amazonaws.com.cn)

A default region the vendored data does not know only warns. AWS launches regions faster than the data is refreshed, and botocore's region-shape rules (cn-*, us-gov-*, ...) still place it; anything else falls back to aws, which is what the AWS SDKs do too.

Running a China, GovCloud, ISO or EUSC deployment

Start Floci with a default region in the partition, then point clients at it with a region in the same partition and an endpoint override:

docker run --rm -p 4566:4566 \
  -e FLOCI_DEFAULT_REGION=cn-north-1 \
  floci/floci:latest

AWS_DEFAULT_REGION=cn-north-1 bin/awslocal sts get-caller-identity
# "Arn": "arn:aws-cn:iam::000000000000:root"

With the AWS CLI directly, pass --region cn-north-1 --endpoint-url http://localhost:4566; with an SDK, set the region and the endpoint override on the client. The override replaces the partition's real host (amazonaws.com.cn here) for transport only: the SDK still signs for the region you gave it, and that signing region is what places each request in its partition (see below). If clients reach Floci on another host or port than http://localhost:4566, set FLOCI_BASE_URL to match, or URLs Floci returns, such as SQS queue URLs and pre-signed URLs, keep pointing at the default. FLOCI_HOSTNAME is enough when only the host differs: it replaces the host and keeps the port.

Which partition a request belongs to

Each request's partition comes from the region in its SigV4 credential scope, exactly as LocalStack and moto do it. A client signing cn-north-1 is a China client even when Floci was started with us-east-1, so one process can serve several partitions at once. Requests without a credential, and background work (pollers, schedulers, startup hooks), use the deployment's partition.

JSON 1.1 service dispatch uses the region selected for the request, including a presigned X-Amz-Credential query scope when the request filter accepts it. An applicable Authorization header takes precedence over query credentials; requests without an admitted credential scope use the configured default region. Authorization and execution therefore use the same regional namespace.

The scope region of a global service is its signing region, not a place to put regional resources: China IAM always signs cn-north-1 even from Ningxia, GovCloud IAM signs us-gov-west-1. Floci uses it to pick the partition and nothing else. The <partition>-global pseudo-regions the SDKs accept (aws-global, aws-cn-global, ...) resolve to their partition as well; aws-eusc publishes none. AWS never signs with one (the SDKs map each to a real signing region), so a scope that names one is served as the partition's implicit global region: a request signed aws-cn-global is a cn-northwest-1 request, and no ARN or storage namespace carries the pseudo-region.

A scope region that no partition publishes or admits by its region pattern, such as polygondwanaland-west-1, is refused with a 400: an S3-signed request gets S3's AuthorizationHeaderMalformed ("the region '...' is wrong"), every other service gets InvalidSignatureException. On AWS such a request never resolves a host; moto (MOTO_ALLOW_NONEXISTENT_REGION) and LocalStack (ALLOW_NONSTANDARD_REGIONS) refuse it too. The pattern rule is the AWS SDKs' own, so a region AWS launches after the vendored data was refreshed (eu-south-9, say) is still served; it is looser than S3's LocationConstraint enum, which stays published-only. Set FLOCI_PARTITIONS_ALLOW_UNKNOWN_REGIONS=true (floci.partitions.allow-unknown-regions) to serve custom labels with their own namespaces. Such a label belongs to the deployment's partition. ARNs minted through Floci's shared region resolver use that partition too; services that build their ARNs directly still fall back to aws for a label no partition publishes.

A region label containing : is always refused because the colon separates ARN fields and storage identities. This also applies to FLOCI_DEFAULT_REGION; Floci refuses to start with a colon in that setting. Existing stored namespaces are not migrated or deleted by this check.

What changes per partition

  • ARNs: regional resources carry the partition of their region (arn:aws-cn:sqs:cn-north-1:...); regionless resources (IAM, S3, STS, CloudFront, Route 53, Organizations) carry the request's partition.
  • DescribeRegions: the request's partition's regions, with the partition's endpoints. As on AWS, a commercial deployment lists the 17 regions that need no opt-in by default and all 34 with AllRegions=true, where opt-in regions report not-opted-in.
  • Hostnames: AWS-shaped hosts in responses (an HTTP API's ApiEndpoint, a bucket's RegionalDomainName and WebsiteURL, Cognito and EKS OIDC issuers, EC2 public DNS names) use the DNS suffix of their region's partition, so a cn-north-1 API answers <id>.execute-api.cn-north-1.amazonaws.com.cn. DualStackDomainName is only returned where S3 publishes a dual-stack endpoint.
  • Hostname recognition: every published region id and DNS suffix, in every partition, is recognised in an S3 virtual-host, execute-api, ECR image or CloudFront origin hostname.
  • S3 CreateBucket: as on AWS, the us-east-1 endpoint takes any LocationConstraint but its own, and every other regional endpoint requires a constraint naming exactly its region (IllegalLocationConstraintException otherwise). A China or GovCloud client must send the constraint, which the AWS SDKs do; GetBucketLocation still answers an empty constraint only for us-east-1, in every partition.
  • AWS Sign-In: the cross-device login redirect is accepted on the Sign-In host of the deployment's partition (<region>.signin.amazonaws.cn in China, <region>.signin.amazonaws-us-gov.com in GovCloud), read from botocore's signin endpoint ruleset into aws/partitions.json, and on Floci's own endpoint. The device-authorization client ids are the same literal in every partition, as the Sign-In model spells them.
  • Hosted zones and console URLs: load balancer and S3 website hosted zone ids come from a per-region table (aws/region-facts.json, generated from the Terraform provider and the CDK, which transcribe the AWS General Reference, and from the General Reference itself and the China and GovCloud user guides); Network load balancers have their own zone, distinct from the Application/Classic one. The CloudFront hosted zone is published for aws and aws-cn; the SAML sign-on URL for five partitions. The console link in a CodePipeline approval notification uses the console host of the pipeline's partition (console.amazonaws.cn in China, console.amazonaws-us-gov.com in GovCloud), as the China and GovCloud user guides state it; the path after the host is the commercial console's. A generated CloudFront distribution domain name ends in cloudfront.cn in China, as the China guide names the default CloudFront domain, unless floci.services.cloudfront.domain-suffix is set. A regional API Gateway custom domain reports the regional hosted zone the AWS General Reference publishes for its region. The ISO and EUSC regions have no load balancer hosted zones, and only the two ISO-F regions have an S3 website zone; where a table has no row the field is omitted rather than guessed. The one exception is API Gateway, whose response always carries a zone: a region with no row reports a placeholder, listed under the open questions below. An EDGE API Gateway REST API or custom domain is refused outside the commercial partition (BadRequestException): GovCloud, EUSC and ISO have no CloudFront, and China has no edge-optimized API Gateway (China API Gateway). A Lambda function URL is refused in GovCloud and China (InvalidParameterValueException on CreateFunctionUrlConfig), where the GovCloud and China guides list function URLs as not available. A Cognito user pool custom domain (CustomDomainConfig) is refused in GovCloud and EUSC (InvalidParameterException), where the GovCloud and EUSC guides list custom domains as not available; prefix domains work there.
  • VPC endpoint service names: interface endpoints (as DescribeVpcEndpointServices lists them) are com.amazonaws.<region>.<service> everywhere, except the (region, service) pairs the CDK lists for China, ISO and EUSC, which reverse the DNS suffix (cn.com.amazonaws.cn-north-1.lambda). GovCloud keeps com.amazonaws. Gateway endpoints and their AWS-managed prefix lists (S3, DynamoDB) are com.amazonaws.<region>.<service> in every partition. S3 offers both kinds: where the two names agree it is one service carrying both types, and in China it is listed twice, the gateway com.amazonaws.cn-north-1.s3 and the interface cn.com.amazonaws.cn-north-1.s3.
  • Lambda runtime images pull from ECR Public (public.ecr.aws), which exists only in the commercial partition; point FLOCI_SERVICES_LAMBDA_ECR_BASE_URI at a mirror elsewhere.
  • WAF CLOUDFRONT scope: available only where CloudFront exists (aws, aws-cn), and its resources live in the partition's implicit global region (cn-northwest-1 in China).

What does not change

  • Service principals are <service>.amazonaws.com in every partition; that is the rule the AWS CDK applies today, and everything Floci emits (generated trust policies, CloudTrail's eventSource, service-linked role paths) uses it. The older per-partition forms the CDK retired (elasticmapreduce.amazonaws.com.cn, logs.<region>.amazonaws.com.cn, config.c2s.ic.gov) are still accepted wherever Floci matches a principal against a policy, such as a role's trust policy, so a policy written in either form works; matching stays exact and case-sensitive. CreateServiceLinkedRole given a legacy form creates the same role as the universal one: its name, path and trust policy all use <service>.amazonaws.com.
  • XML namespaces and the S3 canned-ACL group URIs (http://acs.amazonaws.com/groups/...) are identifiers, not hosts.
  • AWS managed policy ARNs keep the literal aws account slot: arn:aws-cn:iam::aws:policy/AdministratorAccess. The catalog Floci bundles is the commercial one; every other partition's is derived from it on first use, with the partition in every ARN (what AWS's own SAM translator does) and the partition's DNS suffix in the region-bearing kms:ViaService hosts (s3.*.amazonaws.com.cn). Service principals and service-linked role paths are the same in every partition and are left alone. Whether AWS's China or GovCloud documents differ in content beyond that is an open question below.

Partition-absent services

AWS publishes which services exist in each partition (CloudFront is not in GovCloud, Lightsail is not in China). On AWS a request for an absent service never reaches an API: the SDK fails to resolve the host and reports an UnknownHostException. Floci serves every enabled service in every partition by default.

Set FLOCI_PARTITIONS_STRICT=true (floci.partitions.strict) to mirror AWS instead. A request whose SigV4 signing name the request's partition does not publish is refused with a 404 UnknownOperationException whose message names the service and the partition; Floci cannot fail DNS, so this is the same shape the unknown-service guard uses. The check reads the vendored service list, matching the signing name directly or through the endpoint prefixes it covers (ecr signs for api.ecr, bedrock for bedrock-runtime), so a China ECR client is served while a GovCloud CloudFront client is refused. Only a service the data lists in some other partition is refused: endpoints.json omits the newer services that ship an endpoint ruleset alone (FIS, MWAA, S3 Tables), and those are served everywhere.

A partition also offers a service when that service's endpoint ruleset names the partition in a branch with its own endpoint, even where endpoints.json leaves it out: IAM, Route 53, Budgets and Cost Explorer in aws-eusc (iam.eusc-de-east-1.amazonaws.eu), IAM and Cost Explorer in aws-iso-e. The vendored data records these under servicesFromRulesets. The execute-api signing name is never refused: API Gateway's invoke endpoints and its WebSocket management API (apigatewaymanagementapi) sign with it as well as Connect Participant, and endpoints.json lists the API Gateway side nowhere, so the data cannot say where the name is served.

STS is regionalized everywhere and its global host sts.amazonaws.com exists only in aws, so IAM's GetAccountSummary reports GlobalEndpointTokenVersion only there.

An IAM resource (user, group, role, policy, instance profile, OIDC provider) is created in the request's partition and keeps it: a rename signed for another partition does not move it. On AWS an account belongs to one partition, but one Floci process serves them all, so anything derived from a stored resource follows that resource. A role's sessions (assumed-role) and the OIDC provider its web-identity trust policy names take the stored role's partition, whichever partition the request's RoleArn names, so AssumeRole and a later GetCallerIdentity agree whatever region each call is signed for. The credential report is kept per partition, so its root row always names the caller's. ARNs with nothing stored behind them, the root fallback of GetCallerIdentity and federated-user, take the request's partition.

How it is tested

  • The partition rules themselves (partition and region lookup, ARN minting, hostnames, service principals, managed-policy rewriting, STS) have unit tests over all eight partitions.
  • Through the emulator, IAM ARNs run in all eight partitions, and a smoke test creates one resource per service in every non-commercial partition that publishes the service and checks its ARN or host. It covers every service that mints ARNs or hosts; the few without a case are listed with the reason in src/test/resources/partition/smoke-exemptions.tsv, and a new service needs a case there or a recorded exemption. Most other partition-dependent behaviour (EC2 regions and DNS names, hosted zones, VPC endpoint names, Lambda layers, Step Functions integration ids, strict mode) is tested in one or two partitions, nearly always China.
  • End to end, the nightly Partition Compatibility workflow runs the Java SDK compatibility suite against a Floci deployed with FLOCI_DEFAULT_REGION=cn-north-1, with the SDK clients signing for cn-north-1, so the SDK's own China partition handling has to round-trip. Its list of known failures, .github/ci/compat-partition-allowlist-cn-north-1.txt, is empty, so any failure fails the run. No other partition, and no other compatibility suite (the Python, Go, Node and AWS CLI suites, CDK, Terraform, OpenTofu), runs outside the commercial partition.

Known gaps

  • One process serving several partitions shares global state. S3 bucket names are one namespace, and ListBuckets lists buckets created from every partition; IAM, Organizations, Route 53, CloudFront and the IAM Identity Center instance keep one set of resources per account, whichever partition a request is signed for. AWS keeps them per partition. A deployment that serves one partition is unaffected. For the same reason, STS AssumeRole, EKS Pod Identity and EKS add-ons accept a role ARN from any partition and resolve it to the account's role of that path and name; the session is named with the role's own ARN.
  • AWS managed policies are the commercial catalog in every partition, with their ARNs and regional hosts rewritten; AWS publishes no per-partition list.
  • Client tooling that computes partition values itself (CDK bootstrap and AWS::Partition, Terraform's aws_partition, SAM) is not tested outside the commercial partition, and neither is any partition but China end to end.

Open questions

These values have no published source Floci can cite, so it does not guess them; they keep the commercial value or Floci's own base host until sourced:

  • the STS web-identity audience outside the commercial partition;
  • the EKS Pod Identity token audience (pods.eks.amazonaws.com) outside the commercial partition;
  • the Lambda function-URL host in the ISO and EUSC partitions (function URLs are refused in GovCloud and China, where the partition guides list them as not available);
  • whether AWS managed policy documents differ in content in China or GovCloud;
  • the API Gateway regional hosted zone in the regions the General Reference does not list (China, ISO, EUSC and ap-southeast-6): a custom domain there reports Z2FDTNDATAQYL2, a placeholder that is no AWS zone, so a Route 53 alias built from it resolves to nothing on AWS;
  • the availability-zone id prefix of the ISO and EUSC regions: zone ids there keep the whole region (us-iso-east-1-az1), where the other partitions get AWS's short prefix (use1-az1, usgw1-az1, cnn1-az1);
  • S3 LocationConstraint enum values and Route 53 hosted zones for the ISO and EUSC regions;
  • the management console host in the ISO and EUSC partitions, where a CodePipeline approval notification keeps linking to the commercial console.aws.amazon.com;
  • the SAML sign-on URL in aws-iso-e, aws-iso-f and aws-eusc, where assertions keep being checked against the commercial https://signin.aws.amazon.com/saml;
  • the exact error AWS WAF returns for the CLOUDFRONT scope in a partition without CloudFront (GovCloud, the ISO partitions): Floci refuses it with WAFInvalidParameterException and its own message.