Skip to content

feat: Add vertical autoscaling configuration for stream processors - #4665

Merged
jwongmongodb merged 15 commits into
masterfrom
CLOUDP-422510-stream-processor-autoscaling
Aug 26, 2026
Merged

jwongmongodb merged 15 commits into
masterfrom
CLOUDP-422510-stream-processor-autoscaling

Conversation

@jwongmongodb

@jwongmongodb jwongmongodb commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Phase 1 vertical autoscaling support to mongodbatlas_stream_processor and its singular and plural data sources:

  • optional options.autoscaling block with optional server-defaulted min_tier and max_tier
  • computed, read-only effective_tier, which reports the processor's current running tier
  • tier remains the user-configured baseline tier; it does not autoscale or drift
  • options.dlq and options.autoscaling are independently optional; an explicitly empty options object is rejected

Included

  • Resource and data-source schema, model, conversion, and CRUD updates.
  • Declarative disable behavior: removing options.autoscaling sends an explicit options.autoscaling: null PATCH. If autoscaling is the only option, omit options entirely; if a DLQ remains, remove only options.autoscaling.
  • Correct API shape for :startWith, where autoscaling is top-level rather than nested in options.
  • Unit and acceptance coverage for conversions, effective_tier, create/update requests, optional DLQ, block-removal disablement, server-default bounds, and empty-options validation.
  • Regenerated documentation, example configuration, and release-note entries.

Validation

  • Targeted unit tests and provider verification pass locally.

  • Cloud Dev E2E validation confirmed the explicit PATCH payload:

    {
      "options": {
        "autoscaling": null
      }
    }

    Cloud Dev accepted the update and cleared autoscaling.

Draft status

This PR remains a draft while the final review and full CI run complete.

Expected Terraform release: August 27, 2026.

Comment thread docs/data-sources/stream_processor.md Outdated
db = "exampleDb"
}
autoscaling = {
enabled = true

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question on the Terraform shape: do we need to expose enabled in the autoscaling block? I know in the design/td, we have enabled to track if autoscaling is enabled or disabled. But given the API Contract doc scenario, when an autoscaling config is disabled, the whole object is omitted from the response and subsequent GET calls for the stream processor.

Based on the API behavior we tested in Cloud Dev, the presence of options.autoscaling enables autoscaling, and removing the block disables it—the provider sends enabled: false on the PATCH, and the backend clears the configuration. Since enabled = false cannot round-trip and we reject it today, enabled seems redundant as a Terraform argument.

Could we instead make the schema:

options = {
  autoscaling = {
    min_tier = "SP10"
    max_tier = "SP50"
  }
}

Then the provider can continue translating block presence/removal to enabled: true / enabled: false in the API request. This feels more idiomatic for Terraform and avoids requiring users to set a field that only has one valid value.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabled seems redundant as a Terraform argument

I agree here. I am curious why we didnt apply the same judgement at the API level, why does autoScaling.enabled actually exist?

@jwongmongodb jwongmongodb Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the PATCH behavior, excluding the autoscaling config in a PATCH API does not mean that it will disable it since omission means to preserve the existing config for the PATCH contract.

So we needed a way to disable the autoscaling field with the enabled field, for terraform we can simplify this with just the config.

@jwongmongodb jwongmongodb Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we okay with this terraform behavior to exclude enabled and have the existence of the Autoscaling config be the enabling factor for terraform @AgustinBettati. If yes, I can make the change now.

EX:
removing autoscaling config from an existing stream processor will disable autoscaling.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this cleanup, let me know if this should be reverted to add back enabled to the autoscaling field. I believe this change to remove the enabled field is a better user experience.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am aligned, lets make sure to capture this decision in associated TD for future reference.
In terms of the PATCH behaviour on the API side, one option we could have used (not sure if too late now) is that sending an explicit null (e.g. autoScaling = null) in the PATCH is the way of signalling we want to unset the property (https://mongodb.github.io/ipa/107#guidance point 5).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated and tagged you in the updated TD reference to the terraform config: https://docs.google.com/document/d/1q5mmlV63bEk006CXpDEWM3nXDa41USzgvE_nvHkZGGs/edit?disco=AAACF73K4vg

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also made a post in the thread regarding the level of effort needed to make autoscaling = null before the release this Thursday here.

@jwongmongodb jwongmongodb Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated in this slack thread, I updated the provider to use an explicit autoscaling: null PATCH when the autoscaling block is removed from an existing Terraform-managed processor.

I verified this in Cloud Dev with provider debug logging. The provider sent:

{
  "name": "autoscaling-e2e-processor",
  "options": {
    "autoscaling": null
  },
  "pipeline": [
    {
      "$source": {
        "connectionName": "sample_stream_solar"
      }
    },
    {
      "$emit": {
        "connectionName": "__testLog"
      }
    }
  ],
  "tier": "SP10"
}

Cloud Dev accepted the update and cleared autoscaling.

This keeps the Terraform behavior declarative, presence of the autoscaling block enables it, while removing it disables it without exposing the API transport-level enabled field in Terraform configuration.

@AgustinBettati AgustinBettati left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Providing initial review

Comment thread internal/service/streamprocessor/resource_schema.go
Comment thread internal/service/streamprocessor/resource_schema.go Outdated
Comment thread internal/service/streamprocessor/resource_schema.go Outdated
Comment thread docs/data-sources/stream_processor.md Outdated
db = "exampleDb"
}
autoscaling = {
enabled = true

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabled seems redundant as a Terraform argument

I agree here. I am curious why we didnt apply the same judgement at the API level, why does autoScaling.enabled actually exist?

Comment thread internal/service/streamprocessor/resource_schema.go Outdated
Comment thread internal/service/streamprocessor/autoscaling.go Outdated
Comment thread internal/service/streamprocessor/autoscaling.go Outdated
Comment thread internal/service/streamprocessor/model.go Outdated
Extend mongodbatlas_stream_processor and its data sources with the Phase 1
vertical autoscaling config: options.autoscaling { enabled, min_tier, max_tier }
and the read-only effective_tier attribute.

- Schema, model, and conversions with PATCH tri-state semantics (omit=preserve,
  explicit false/block-removal=disable+clear); startWith carries autoscaling top-level.
- Plan-time validator rejecting min_tier/max_tier when enabled=false.
- Unit tests (conversions, effective_tier, create/update reqs) and acceptance
  tests (create/disable, validator).
- Regenerated resource + data source docs and updated example.

WIP: the autoscaling API fields are still @hidden, so this builds against a local
SDK stub (.sdkstub/ + a go.mod replace kept local, not committed). Not releasable
until the official SDK ships the fields.
… enabled=false

The backend clears a disabled autoscaling config, so a GET after disable returns no
autoscaling object. An explicit enabled=false therefore cannot round-trip and produces
a 'provider produced inconsistent result after apply' error. Reject enabled=false at
plan time with guidance to remove the options.autoscaling block instead; the provider
still sends the explicit disable to the API when the block is removed. Update schema
descriptions, docs, and the validator/acceptance test accordingly.
@jwongmongodb
jwongmongodb force-pushed the CLOUDP-422510-stream-processor-autoscaling branch from 56407e1 to c17c42a Compare August 25, 2026 13:16
@jwongmongodb
jwongmongodb marked this pull request as ready for review August 25, 2026 18:51
@jwongmongodb
jwongmongodb requested review from a team as code owners August 25, 2026 18:51
Copilot AI lite review requested due to automatic review settings August 25, 2026 18:51
@github-actions

Copy link
Copy Markdown
Contributor

APIx bot: a message has been sent to Docs Slack channel

@augmentcode

augmentcode Bot commented Aug 25, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Adds Phase 1 vertical autoscaling support for stream processors.

Changes:

  • Adds optional options.autoscaling with server-defaulted min_tier and max_tier.
  • Adds computed effective_tier to the resource and both stream-processor data sources.
  • Keeps tier as the configured baseline while exposing the active tier separately.
  • Makes DLQ and autoscaling independently optional, while rejecting empty options objects.
  • Converts Terraform autoscaling objects to SDK requests and maps API responses back into state.
  • Implements PATCH tri-state behavior, including explicit autoscaling: null when the block is removed.
  • Uses the top-level autoscaling payload required by the :startWith endpoint.
  • Extends unit and acceptance coverage for conversion, defaults, removal, requests, and effective-tier state.
  • Regenerates resource/data-source documentation, updates the example, and adds release notes.
Technical note: The implementation relies on block presence as Terraform's autoscaling enablement signal and preserves API-specific DLQ clear semantics.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Phase 1 vertical autoscaling support for mongodbatlas_stream_processor (resource + singular/plural data sources) by introducing an optional options.autoscaling configuration block, a computed effective_tier read-only attribute, and update semantics to explicitly clear autoscaling via PATCH when the block is removed.

Changes:

  • Adds options.autoscaling (with server-defaulted min_tier / max_tier) and introduces computed effective_tier across resource and data sources.
  • Implements tri-state update behavior to preserve/clear autoscaling and DLQ independently, including explicit autoscaling nulling on removal.
  • Updates tests, docs, examples, and changelog entries to cover and document autoscaling behavior and the new attribute.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/service/streamprocessor/resource.go Sends autoscaling at top-level for :startWith on create/update start flows; passes prior state into update request builder.
internal/service/streamprocessor/resource_test.go Adds acceptance coverage for enabling autoscaling and disabling it by removing the block.
internal/service/streamprocessor/resource_schema.go Adds options.autoscaling, makes options.dlq optional, adds effective_tier, and enforces non-empty options.
internal/service/streamprocessor/options_validator.go Adds validator to reject explicitly empty options objects.
internal/service/streamprocessor/options_validator_test.go Unit tests for the new options validator.
internal/service/streamprocessor/model.go Adds autoscaling/DLQ update tri-state resolution, adds effective tier mapping, and adds autoscaling conversions.
internal/service/streamprocessor/model_test.go Extends unit coverage for autoscaling conversions, effective tier, and update PATCH semantics.
internal/service/streamprocessor/dlq.go Extracts DLQ plan/state resolution into helpers for update tri-state semantics.
internal/service/streamprocessor/autoscaling.go Adds autoscaling TF model, conversions, plan extraction, and update tri-state resolution.
examples/mongodbatlas_stream_processor/main.tf Updates example to include baseline tier and options.autoscaling.
docs/resources/stream_processor.md Documents options.autoscaling, effective_tier, and the non-empty options constraint.
docs/data-sources/stream_processors.md Documents options.autoscaling and effective_tier in plural data source output.
docs/data-sources/stream_processor.md Documents options.autoscaling and effective_tier in singular data source output.
.changelog/4665.txt Adds release-note entries for the resource and both data sources.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 223 to 226
func ConvertOptionsToTF(ctx context.Context, options *admin.StreamsOptions) (*types.Object, diag.Diagnostics) {
if options == nil || !options.HasDlq() {
if options == nil || (!options.HasDlq() && options.Autoscaling == nil) {
return new(types.ObjectNull(OptionsObjectType.AttributeTypes())), nil
}

@jwongmongodb jwongmongodb Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This compiles as written. The repository uses Go 1.26.4 (go.mod), where new accepts either a type or an expression. types.ObjectNull(...) returns a types.Object, so this produces the required *types.Object.

Verified locally with:

go test ./internal/service/streamprocessor -run '^$' -count=1
make build

- `failover_enabled` (Boolean) Indicates whether this stream processor is eligible for failover. When `true`, an operator can trigger a failover event to migrate the stream processor to a secondary region configured in the workspace's `failover_regions`. Requires an Atlas-to-Atlas or Atlas-to-Kafka pipeline with `failover_regions` configured on the workspace.
- `id` (String) Unique 24-hexadecimal character string that identifies the stream processor.
- `options` (Attributes) Optional configuration for the stream processor. (see [below for nested schema](#nestedatt--options))
- `options` (Attributes) Optional configuration for the stream processor. Empty `options` objects are not supported. (see [below for nested schema](#nestedatt--options))

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AgustinBettati
I made dlq optional so it can be configured independently from autoscaling, which matches the MMS API contract.

This exposed a removal transition that the previous schema could not represent: historically, dlq was required whenever options was present, so Terraform could never plan a processor with options but no DLQ.

For PATCH, MMS/SPM treats an omitted DLQ as “preserve the existing DLQ” and an empty DLQ object (dlq: {}) as the explicit remove signal. The provider now translates removal of a configured Terraform DLQ into that empty-object PATCH payload.

I also added validation that rejects options = {}. If removing DLQ leaves no other option configured, users should omit options entirely. This keeps the Terraform state shape aligned with the API response, which omits options when neither DLQ nor autoscaling is configured.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach makes sense.

an empty DLQ object (dlq: {}) as the explicit remove signal

Following the sibling autoScaling property, I would be consistent in allowing dlq = null as the removal signal in the API side. Also aligning to https://mongodb.github.io/ipa/107#guidance. (not urgent but for considering)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created this ticket for DLQ unsetting behavior https://jira.mongodb.org/browse/CLOUDP-439044

@erabil-mdb erabil-mdb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

}
// Block presence is Terraform's enablement signal. The API requires this
// transport field for create/PATCH semantics, but it is not exposed in state.
req := &admin.StreamsAutoscaling{Enabled: new(true)}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately, enabled=true needs to be sent to the API for autoscaling to work so this logic needs to stay.

if plan.Tier.ValueString() != "" {
startWithOptions.SetTier(plan.Tier.ValueString())
}
// On the :startWith endpoint, `autoscaling` is TOP-LEVEL (no options wrapper).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is from a convenience endpoint from the adminAPI where the terraform provider calls startsWithOptions if the state=started is used in the stream processor.

@jwongmongodb
jwongmongodb force-pushed the CLOUDP-422510-stream-processor-autoscaling branch from 5beb161 to 12e317c Compare August 26, 2026 00:35
}

func TestAccStreamProcessor_withAutoscaling(t *testing.T) {
func TestAccStreamProcessor_withOptionsDLQAutoscaling(t *testing.T) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this now tests the options change with DLQ unsetting and setting with autoscaling setting and unsetting, also tests :startsWithOptions with autoscaling

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice test 👍

@AgustinBettati AgustinBettati left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the follow ups here

@jwongmongodb
jwongmongodb merged commit 0c8f72e into master Aug 26, 2026
51 checks passed
@jwongmongodb
jwongmongodb deleted the CLOUDP-422510-stream-processor-autoscaling branch August 26, 2026 14:25
svc-apix-Bot added a commit that referenced this pull request Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants