Skip to content

[Discussion] sst.aws.Cluster() in dev mode #6303

@abgutierrez

Description

@abgutierrez

Hi there,

First of all, thank you for building SST — I currently have several projects running in production using sst/sst. I’m now trying to adopt more native SST components beyond the lower-level Pulumi ones. I really enjoy working with sst.aws.Service, and I’m trying to better understand the design decisions around local development for ECS-based services.

Context

I’m using sst.aws.Service() to deploy ECS services on AWS. When running sst dev, the workflow still creates or references an ECS cluster in AWS, because the Service constructor requires a cluster to be provided via args.cluster.

From what I’ve been able to observe, there doesn’t seem to be an alternative way to run local development without also provisioning (or referencing) an ECS cluster in AWS — even though this is only for local development. In production, of course, requiring a real cluster makes complete sense.

Why I’m confused about needing a cluster up front

Looking at the constructor implementation, it appears that the Service exits early when running in dev mode:

constructor(
  name: string,
  args: ServiceArgs,
  opts: ComponentResourceOptions = {},
) {
  super(__pulumiType, name, args, opts);
  this._name = name;

  const self = this;
  const clusterArn = args.cluster.nodes.cluster.arn;
  const clusterName = args.cluster.nodes.cluster.name;
  const region = getRegionOutput({}, opts).name;
  const dev = normalizeDev();
  const wait = output(args.wait ?? false);
  const architecture = normalizeArchitecture(args);
  const cpu = normalizeCpu(args);
  const memory = normalizeMemory(cpu, args);
  const storage = normalizeStorage(args);
  const containers = normalizeContainers("service", args, name, architecture);
  const lbArgs = normalizeLoadBalancer();
  const scaling = normalizeScaling();
  const capacity = normalizeCapacity();
  const vpc = normalizeVpc();

  const taskRole = createTaskRole(name, args, opts, self, !!dev);

  this.dev = !!dev;
  this.cloudmapNamespace = vpc.cloudmapNamespaceName;
  this.taskRole = taskRole;

  if (dev) {
    this.devUrl = !lbArgs ? undefined : dev.url;
    registerReceiver();
    return;
  }

  [...]
}

Because the if (dev) { ... return; } branch exits relatively early, I’m trying to understand why a fully defined ECS cluster is still required upfront, along with all the associated normalization logic.

Observations

  • Many of the normalization steps (region, VPC, load balancer, CPU/memory, etc.) are clearly necessary for a real ECS deployment.
  • However, for local development, it seems that several of these validations could potentially be skipped or deferred.
  • Requiring an ECS cluster during sst dev increases the initial startup time and can introduce unnecessary AWS cost if clusters are kept running only for development purposes.

Questions

  • Is it intentional that sst.aws.Service requires a real ECS cluster even when running in dev mode?

  • Is there an architectural reason why cluster-related normalization must happen before the early dev return?

  • Is there any plan to introduce something like:

    • a lightweight or mocked ClusterArgs for dev, or
    • an extension of Cluster with explicit dev-only capabilities (similar in spirit to how EKS local workflows are handled)?

If this behavior is by design, I’d really appreciate any insight into the rationale behind it, or pointers to documentation or code paths that explain the constraints.

Thanks again for the project, and happy New Year! 🎉

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions