Repository: couchbasecloud/terraform-provider-couchbase-capella
Pull request #286: [AV-98659] Implement Free Tier On Off 
Author: login: SaicharanCB
Labels: name: enhancement
description: New feature or request
Created: 2025-04-10T16:44:08Z | Merged: 2025-04-18T20:10:25Z

<!-- REMINDER: All testing and verification for your change should be completed within localdev or a sandbox environment.
ONLY MERGE INTO MAIN IF CHANGES ARE TESTED, VERIFIED AND QUALITY CHECKED THOROUGHLY

Merging to main == merging to PRODUCTION.
-->

## Jira

* AV-98659

## Description

This PR is to add the free-tier cluster turn on/off resource
<!-- What does this change do? Why is it needed? -->

## Type of Change

- [ ] Bug fix (non-breaking change which fixes an issue). Please, add the "bug" label to the PR.
- [x] New feature (non-breaking change which adds functionality). Please, add the "enhancement" label to the PR.
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected). Please, add the "breaking change" label to the PR.
- [ ] This change requires a documentation update
- [ ] Documentation fix/enhancement

## Manual Testing Approach
https://docs.google.com/document/d/1Hj9QBiz79YlBSRgOUD82ywlHf4hb9YkvZkFrfKcprNM/edit?tab=t.wstvye1brog

### How was this change tested and do you have evidence? _**(REQUIRED: Select at least 1)**_

- [x] Manually tested
- [ ] Unit tested
- [ ] Acceptance tested
- [ ] Unable to test / will not test (Please provide comments in section below)

### Testing

<details open>
  <summary>Testing</summary>
  <!-- Provide your testing proof within this collapsible segment-->
  https://docs.google.com/document/d/1Hj9QBiz79YlBSRgOUD82ywlHf4hb9YkvZkFrfKcprNM/edit?tab=t.wstvye1brog
</details>

## Required Checklist:

- [x] I have checked that this change does not generate any credentials and that **they are NOT accidentally logged anywhere**.
- [x] I have added tests that prove my fix is effective or that my feature works per HashiCorp requirements
- [x] I have added any necessary documentation (if required)
- [ ] I have run make fmt and formatted my code
- [ ] I have made sure that no schema field is marked with both requiresReplace and computed
## Further comments


Diff:
diff --git a/examples/free_tier_cluster_on_off/README.md b/examples/free_tier_cluster_on_off/README.md
new file mode 100644
index 000000000..e6635e6f7
--- /dev/null
+++ b/examples/free_tier_cluster_on_off/README.md
@@ -0,0 +1,275 @@
+# Capella Free Tier Cluster On/Off Example
+
+This example demonstrates how to use the Capella Terraform provider to turn off and on a free-tier cluster
+
+To run, configure your Couchbase capella provider as described in README in the root of this project
+
+# Example Walkthrough
+
+
+In this example, we are going to do the following.
+
+1. CREATE: Switch the free-tier cluster and assosciated app-service if any to on/off
+2. UPDATE: Update the current free-tier cluster state to on/off
+3. IMPORT: Import a free-tier cluster state that exists in Capella but not in terraform
+
+If you check the `terraform.template.tfvars` file - Make sure you copy the file to `terraform.tfvars` and update the values of the variables as per the correct organization access.
+
+## CREATE
+### View the plan for the resources that Terraform plan will create
+
+Command: `terraform plan`
+
+Sample Output:
+```
+ $terraform plan 
+╷
+│ Warning: Provider development overrides are in effect
+│ 
+│ The following provider development overrides are set in the CLI configuration:
+│  - couchbasecloud/couchbase-capella in /Users/saicharanrachamadugu/go/bin
+│ 
+│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
+╵
+
+Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+  + create
+
+Terraform will perform the following actions:
+
+  # couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off will be created
+  + resource "couchbase-capella_free_tier_cluster_on_off" "new_free_tier_cluster_on_off" {
+      + cluster_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + organization_id = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + project_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + state           = "off"
+    }
+
+Plan: 1 to add, 0 to change, 0 to destroy.
+
+Changes to Outputs:
+  + new_free_tier_cluster_on_off = {
+      + cluster_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + organization_id = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + project_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + state           = "off"
+    }
+
+─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+
+Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
+```
+
+### Apply the plan to create the resources
+
+Command: `terraform apply`
+
+Sample Output:
+```
+ $terraform apply
+╷
+│ Warning: Provider development overrides are in effect
+│ 
+│ The following provider development overrides are set in the CLI configuration:
+│  - couchbasecloud/couchbase-capella in /Users/saicharanrachamadugu/go/bin
+│ 
+│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
+╵
+
+Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+  + create
+
+Terraform will perform the following actions:
+
+  # couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off will be created
+  + resource "couchbase-capella_free_tier_cluster_on_off" "new_free_tier_cluster_on_off" {
+      + cluster_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + organization_id = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + project_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + state           = "off"
+    }
+
+Plan: 1 to add, 0 to change, 0 to destroy.
+
+Changes to Outputs:
+  + new_free_tier_cluster_on_off = {
+      + cluster_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + organization_id = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + project_id      = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+      + state           = "off"
+    }
+
+Do you want to perform these actions?
+  Terraform will perform the actions described above.
+  Only 'yes' will be accepted to approve.
+
+  Enter a value: yes
+
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Creating...
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still creating... [10s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still creating... [20s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still creating... [30s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still creating... [40s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still creating... [50s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still creating... [1m0s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Creation complete after 1m5s
+
+Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
+
+Outputs:
+
+new_free_tier_cluster_on_off = {
+  "cluster_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+  "organization_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+  "project_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+  "state" = "off"
+}
+
+```
+
+### Verify the resource state
+
+Command: `terraform output new_free_tier_cluster_on_off`
+
+Sample Output:
+```
+$terraform output new_free_tier_cluster_on_off
+
+{
+"cluster_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+"organization_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+"project_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+"state" = "off"
+}
+```
+
+## IMPORT
+
+### Import a resource that exists in Capella but not in terraform
+
+Command: `terraform import couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off cluster_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc,organization_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc,project_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc`
+
+Sample Output:
+```
+$terraform import couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off cluster_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc,organization_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc,project_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Importing from ID "cluster_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc,organization_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc,project_id=ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"...
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Import prepared!
+  Prepared couchbase-capella_free_tier_cluster_on_off for import
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Refreshing state...
+
+Import successful!
+
+The resources that were imported are shown above. These resources are now in
+your Terraform state and will henceforth be managed by Terraform.
+
+```
+## UPDATE
+### Let us edit terraform.tfvars file to change the free-tier cluster state.
+
+Command: `terraform plan`
+
+Sample Output:
+
+```
+$terraform plan
+╷
+│ Warning: Provider development overrides are in effect
+│ 
+│ The following provider development overrides are set in the CLI configuration:
+│  - couchbasecloud/couchbase-capella in /Users/saicharanrachamadugu/go/bin
+│ 
+│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
+╵
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Refreshing state...
+
+Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+  ~ update in-place
+
+Terraform will perform the following actions:
+
+  # couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off will be updated in-place
+  ~ resource "couchbase-capella_free_tier_cluster_on_off" "new_free_tier_cluster_on_off" {
+      ~ state           = "off" -> "on"
+        # (3 unchanged attributes hidden)
+    }
+
+Plan: 0 to add, 1 to change, 0 to destroy.
+
+Changes to Outputs:
+  ~ new_free_tier_cluster_on_off = {
+      ~ state           = "off" -> "on"
+        # (3 unchanged attributes hidden)
+    }
+
+─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
+
+Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
+```
+
+### Apply the plan to update the resources
+
+Command: `terraform apply`
+
+Sample Output:
+```
+$terraform apply
+╷
+│ Warning: Provider development overrides are in effect
+│ 
+│ The following provider development overrides are set in the CLI configuration:
+│  - couchbasecloud/couchbase-capella in /Users/saicharanrachamadugu/go/bin
+│ 
+│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
+╵
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Refreshing state...
+
+Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+  ~ update in-place
+
+Terraform will perform the following actions:
+
+  # couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off will be updated in-place
+  ~ resource "couchbase-capella_free_tier_cluster_on_off" "new_free_tier_cluster_on_off" {
+      ~ state           = "off" -> "on"
+        # (3 unchanged attributes hidden)
+    }
+
+Plan: 0 to add, 1 to change, 0 to destroy.
+
+Changes to Outputs:
+  ~ new_free_tier_cluster_on_off = {
+      ~ state           = "off" -> "on"
+        # (3 unchanged attributes hidden)
+    }
+
+Do you want to perform these actions?
+  Terraform will perform the actions described above.
+  Only 'yes' will be accepted to approve.
+
+  Enter a value: yes
+
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Modifying...
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [10s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [20s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [30s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [40s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [50s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [1m0s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [1m10s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [1m20s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [1m30s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [1m40s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Still modifying... [1m50s elapsed]
+couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off: Modifications complete after 1m55s
+
+Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
+
+Outputs:
+
+new_free_tier_cluster_on_off = {
+  "cluster_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+  "organization_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+  "project_id" = "ffffffff-aaaaaaaa-bbbbbbbbb-cccccc"
+  "state" = "on"
+}
+```
diff --git a/examples/free_tier_cluster_on_off/create_free_tier_cluster_on_off.tf b/examples/free_tier_cluster_on_off/create_free_tier_cluster_on_off.tf
new file mode 100644
index 000000000..9abed5c1f
--- /dev/null
+++ b/examples/free_tier_cluster_on_off/create_free_tier_cluster_on_off.tf
@@ -0,0 +1,12 @@
+output "new_free_tier_cluster_on_off" {
+  value = couchbase-capella_free_tier_cluster_on_off.new_free_tier_cluster_on_off
+}
+
+resource "couchbase-capella_free_tier_cluster_on_off" "new_free_tier_cluster_on_off" {
+  organization_id = var.organization_id
+  project_id      = var.project_id
+  cluster_id      = var.cluster_id
+  state           = var.state
+
+}
+
diff --git a/examples/free_tier_cluster_on_off/main.tf b/examples/free_tier_cluster_on_off/main.tf
new file mode 100644
index 000000000..c0a9ce2c9
--- /dev/null
+++ b/examples/free_tier_cluster_on_off/main.tf
@@ -0,0 +1,12 @@
+terraform {
+  required_providers {
+    couchbase-capella = {
+      source = "couchbasecloud/couchbase-capella"
+    }
+  }
+}
+
+provider "couchbase-capella" {
+  authentication_token = var.auth_token
+}
+
diff --git a/examples/free_tier_cluster_on_off/terraform.template.tfvars b/examples/free_tier_cluster_on_off/terraform.template.tfvars
new file mode 100644
index 000000000..4641a3ee0
--- /dev/null
+++ b/examples/free_tier_cluster_on_off/terraform.template.tfvars
@@ -0,0 +1,6 @@
+auth_token      = "<v4-api-key-secret>"
+organization_id = "<organization_id>"
+project_id      = "<project_id>"
+cluster_id      = "<cluster_id>"
+
+state = "on"
\ No newline at end of file
diff --git a/examples/free_tier_cluster_on_off/variables.tf b/examples/free_tier_cluster_on_off/variables.tf
new file mode 100644
index 000000000..9688fd901
--- /dev/null
+++ b/examples/free_tier_cluster_on_off/variables.tf
@@ -0,0 +1,20 @@
+variable "auth_token" {
+  description = "Authentication API Key"
+  sensitive   = true
+}
+
+variable "organization_id" {
+  description = "Capella Organization ID"
+}
+
+variable "project_id" {
+  description = "Project Name for Project Created via Terraform"
+}
+
+variable "cluster_id" {
+  description = "Capella Cluster ID"
+}
+
+variable "state" {
+  description = "Provides the state cluster to be switched to- on or off"
+}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 83b9d4439..189b2b988 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -234,6 +234,7 @@ func (p *capellaProvider) Resources(_ context.Context) []func() resource.Resourc
 		resources.NewNetworkPeer,
 		resources.NewFlushBucket,
 		resources.NewGSI,
+		resources.NewFreeTierClusterOnOff,
 		resources.NewFreeTierBucket,
 		resources.NewFreeTierCluster,
 		resources.NewFreeTierAppService,
diff --git a/internal/resources/free_tier_cluster_on_off.go b/internal/resources/free_tier_cluster_on_off.go
new file mode 100644
index 000000000..77ac547c0
--- /dev/null
+++ b/internal/resources/free_tier_cluster_on_off.go
@@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierClusterOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId)
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data.
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+// This function is used to manage the activation state of a free-tier cluster.
+// It switches off/on the free-tier cluster based on the provided input and uses the appropriate HTTP method (POST for "on" and DELETE for "off").
+func (f *FreeTierClusterOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf("%s: %s", errorMessageWhileClusterOnOffCreation, api.ParseError(err))
+	}
+	return nil
+}
+
+// retrieveFreeTierClusterOnOff retrieves the current state of the free-tier cluster.
+// if the cluster is in "TurnedOff" state, it returns "off", otherwise it returns "on".
+func (f *FreeTierClusterOnOff) retrieveFreeTierClusterOnOff(ctx context.Context, organizationId, projectId, clusterId string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+	response, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return nil, err
+	}
+	var state string
+	clusterResp := cluster_api.GetClusterResponse{}
+	err = json.Unmarshal(response.Body, &clusterResp)
+	if err != nil {
+		return nil, err
+	}
+
+	if clusterResp.CurrentState != cluster_api.TurnedOff {
+		state = "on"
+	} else {
+		state = "off"
+	}
+
+	refreshedState := providerschema.FreeTierClusterOnOff{
+		ClusterId:      types.StringValue(clusterId),
+		ProjectId:      types.StringValue(projectId),
+		OrganizationId: types.StringValue(organizationId),
+		State:          types.StringValue(state),
+	}
+
+	return &refreshedState, nil
+}
+
+// This function checks the cluster's current state and waits until it matches the desired state.
+// When Turning on the cluster it checks for "Healthy" state and when turning off it checks for "TurnedOff" state.
+func (f *FreeTierClusterOnOff) checkClusterForDesiredStatus(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+
+	var clusterResp cluster_api.GetClusterResponse
+	const timeout = 20 * time.Minute
+	const retryInterval = 3 * time.Second // Added retry delay.
+
+	ctx, cancel := context.WithTimeout(ctx, timeout)
+	defer cancel()
+
+	var desiredState cluster_api.State
+	switch state {
+	case "on":
+		desiredState = cluster_api.Healthy
+	case "off":
+		desiredState = cluster_api.TurnedOff
+	default:
+		return nil, fmt.Errorf("invalid state: %s", state)
+	}
+
+	ticker := time.NewTicker(retryInterval)
+	defer ticker.Stop()
+
+	for {
+		select {
+		case <-ctx.Done():
+			return nil, fmt.Errorf("cluster state check timed out: %w", ctx.Err())
+		case <-ticker.C:
+			response, err := f.Client.ExecuteWithRetry(ctx, cfg, nil, f.Token, nil)
+			if err != nil {
+				return nil, fmt.Errorf("API request failed: %w", err)
+			}
+
+			if err := json.Unmarshal(response.Body, &clusterResp); err != nil {
+				return nil, fmt.Errorf("failed to parse response: %w", err)
+			}
+
+			if clusterResp.CurrentState == desiredState {
+				refreshedState := providerschema.FreeTierClusterOnOff{
+					ClusterId:      types.StringValue(clusterId),
+					ProjectId:      types.StringValue(projectId),
+					OrganizationId: types.StringValue(organizationId),
+					State:          types.StringValue(state),
+				}
+				return &refreshedState, nil
+			}
+
+			tflog.Debug(ctx, fmt.Sprintf("Current cluster state: %s (waiting for %s)", clusterResp.CurrentState, desiredState))
+		}
+	}
+}
diff --git a/internal/resources/free_tier_cluster_on_off_schema.go b/internal/resources/free_tier_cluster_on_off_schema.go
new file mode 100644
index 000000000..976c24873
--- /dev/null
+++ b/internal/resources/free_tier_cluster_on_off_schema.go
@@ -0,0 +1,18 @@
+package resources
+
+import (
+	"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+	"github.com/hashicorp/terraform-plugin-framework/resource/schema"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+func FreeTierClusterOnOffSchema() schema.Schema {
+	return schema.Schema{
+		Attributes: map[string]schema.Attribute{
+			"organization_id": stringAttribute([]string{required, requiresReplace}, validator.String(stringvalidator.LengthAtLeast(1))),
+			"project_id":      stringAttribute([]string{required, requiresReplace}, validator.String(stringvalidator.LengthAtLeast(1))),
+			"cluster_id":      stringAttribute([]string{required, requiresReplace}, validator.String(stringvalidator.LengthAtLeast(1))),
+			"state":           stringAttribute([]string{required}),
+		},
+	}
+}
diff --git a/internal/schema/free_tier_cluster_on_off.go b/internal/schema/free_tier_cluster_on_off.go
new file mode 100644
index 000000000..ed30a198b
--- /dev/null
+++ b/internal/schema/free_tier_cluster_on_off.go
@@ -0,0 +1,38 @@
+package schema
+
+import (
+	"fmt"
+
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+)
+
+// ClusterOnOffOnDemand provides the means to turn the given cluster to on or off state.
+type FreeTierClusterOnOff struct {
+	// OrganizationId is the organizationId of the capella tenant.
+	OrganizationId types.String `tfsdk:"organization_id"`
+
+	// ProjectId is the projectId of the capella tenant.
+	ProjectId types.String `tfsdk:"project_id"`
+
+	// ClusterId is the clusterId of the capella tenant.
+	ClusterId types.String `tfsdk:"cluster_id"`
+
+	// State is the state (on/off) the cluster needs to be turned on/off of the cluster
+	State types.String `tfsdk:"state"`
+}
+
+func (f *FreeTierClusterOnOff) Validate() (map[Attr]string, error) {
+	state := map[Attr]basetypes.StringValue{
+		OrganizationId: f.OrganizationId,
+		ProjectId:      f.ProjectId,
+		ClusterId:      f.ClusterId,
+	}
+
+	IDs, err := validateSchemaState(state, ClusterId)
+	if err != nil {
+		return nil, fmt.Errorf("failed to validate resource state: %s", err)
+	}
+
+	return IDs, nil
+}


Reviews:
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:16:15Z
user: login: PaulomeeCb
body: @SaicharanCB I think you should mention `cluster` in the resource, so everywhere it should be `free_tier_cluster_on_off` instead of `free_tier_on_off`, it'll make it more clear.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:21:06Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:21:30Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:23:49Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:26:59Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:35:51Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:39:42Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:40:29Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:48:56Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:55:39Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T03:56:28Z
user: login: PaulomeeCb
body: Can you add tests for checking what happens when-
1. PFT cluster is off but we still try to switch it off.
2. PFT cluster is on but we still try to switch it on.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T04:03:39Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T07:33:32Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T18:01:51Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T18:01:58Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T18:02:06Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T18:02:34Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T18:03:45Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T18:04:56Z
user: login: PaulomeeCb
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T00:59:58Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T06:12:58Z
user: login: l0n3star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:31:34Z
user: login: l0n3star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:35:27Z
user: login: l0n3star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:37:49Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:41:56Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:44:46Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:45:58Z
user: login: SaicharanCB
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T18:46:32Z
user: login: l0n3star
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T19:31:47Z

Review comments:
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
path: internal/resources/free_tier_on_off.go
user: login: PaulomeeCb
body: Can you check the go imports? Seems out of place
created_at: 2025-04-15T03:16:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,275 @@
+# Capella Free Tier Cluster On/Off Example
+
+This example demonstrates how to use the Capella Terraform provider to turn off and on a free-tier cluster
+
+To run, configure your Couchbase capella provider as described in README in the root of this project
+
+# Example Walkthrough
+
+
+In this example, we are going to do the following.
+
+1. CREATE: Swithc the free-tier cluster and assosciated app-service if any to on/off
path: examples/free_tier_on_off/README.md
user: login: PaulomeeCb
body: ```suggestion
1. CREATE: Switch the free-tier cluster and assosciated app-service if any to on/off
```
created_at: 2025-04-15T03:21:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,275 @@
+# Capella Free Tier Cluster On/Off Example
+
+This example demonstrates how to use the Capella Terraform provider to turn off and on a free-tier cluster
+
+To run, configure your Couchbase capella provider as described in README in the root of this project
+
+# Example Walkthrough
+
+
+In this example, we are going to do the following.
+
+1. CREATE: Swithc the free-tier cluster and assosciated app-service if any to on/off
path: examples/free_tier_on_off/README.md
user: login: PaulomeeCb
body: Also, correct me if I'm wrong but I'm not sure if adding this line - "and assosciated app-service if any to on/off" is appropriate here for free tier, we are not doing anything with the app service right? 
created_at: 2025-04-15T03:23:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+auth_token      = "<v4-api-key-secret>"
+organization_id = "<organization_id>"
+project_id      = "<project_id>"
+cluster_id      = "<cluster_id>"
+
+state = "on"
+
+cluster_onoff_ondemand = {
path: examples/free_tier_on_off/terraform.template.tfvars
user: login: PaulomeeCb
body: Why is this here? This should not be here. Make sure you are not copying incorrectly.
created_at: 2025-04-15T03:26:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf(errorMessageWhileClusterOnOffCreation + api.ParseError(err))
path: internal/resources/free_tier_on_off.go
user: login: PaulomeeCb
body: errorMessageWhileClusterOnOffCreation -  shouldn't this be changed for free tier?
created_at: 2025-04-15T03:35:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,275 @@
+# Capella Free Tier Cluster On/Off Example
+
+This example demonstrates how to use the Capella Terraform provider to turn off and on a free-tier cluster
+
+To run, configure your Couchbase capella provider as described in README in the root of this project
+
+# Example Walkthrough
+
+
+In this example, we are going to do the following.
+
+1. CREATE: Swithc the free-tier cluster and assosciated app-service if any to on/off
path: examples/free_tier_on_off/README.md
user: login: SaicharanCB
body: yeah we do switch off any app services attached with free tier cluster.
created_at: 2025-04-15T03:39:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
path: internal/resources/free_tier_on_off.go
user: login: PaulomeeCb
body: Q. should this be `cluster_id` or `free_tier_cluster_id` ?
created_at: 2025-04-15T03:40:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf(errorMessageWhileClusterOnOffCreation + api.ParseError(err))
+	}
+	return nil
+}
+
+func (f *FreeTierOnOff) retrieveFreeTierClusterOnOff(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+	response, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	//There is no GET endpoint so get the cluster response and check current state
+	clusterResp := cluster_api.GetClusterResponse{}
+	err = json.Unmarshal(response.Body, &clusterResp)
+	if err != nil {
+		return nil, err
+	}
+
+	if clusterResp.CurrentState != cluster_api.TurnedOff {
+		state = "on"
+	} else {
+		state = "off"
+	}
+
+	refreshedState := providerschema.FreeTierClusterOnOff{
+		ClusterId:      types.StringValue(clusterId),
+		ProjectId:      types.StringValue(projectId),
+		OrganizationId: types.StringValue(organizationId),
+		State:          types.StringValue(state),
+	}
+
+	return &refreshedState, nil
+}
+
+func (f *FreeTierOnOff) checkClusterForDesiredStatus(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+
+	var clusterResp cluster_api.GetClusterResponse
+	const timeout = 20 * time.Minute
+	const retryInterval = 3 * time.Second // Added retry delay.
+
+	ctx, cancel := context.WithTimeout(ctx, timeout)
+	defer cancel()
+
+	var desiredState cluster_api.State
+	switch state {
+	case "on":
+		desiredState = cluster_api.Healthy
+	case "off":
+		desiredState = cluster_api.TurnedOff
+	default:
+		return nil, fmt.Errorf("invalid state: %s", state)
+	}
+
+	ticker := time.NewTicker(retryInterval)
+	defer ticker.Stop()
+
+	for {
+		select {
+		case <-ctx.Done():
+			return nil, fmt.Errorf("cluster state check timed out: %w", ctx.Err())
+		case <-ticker.C:
+			response, err := f.Client.ExecuteWithRetry(ctx, cfg, nil, f.Token, nil)
+			if err != nil {
+				return nil, fmt.Errorf("API request failed: %w", err)
+			}
+
+			if err := json.Unmarshal(response.Body, &clusterResp); err != nil {
+				return nil, fmt.Errorf("failed to parse response: %w", err)
+			}
+
+			if clusterResp.CurrentState == desiredState {
+				// Success: Cluster is in desired state.
path: internal/resources/free_tier_on_off.go
user: login: PaulomeeCb
body: what is this comment for?
created_at: 2025-04-15T03:48:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf(errorMessageWhileClusterOnOffCreation + api.ParseError(err))
+	}
+	return nil
+}
+
+func (f *FreeTierOnOff) retrieveFreeTierClusterOnOff(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+	response, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	//There is no GET endpoint so get the cluster response and check current state
+	clusterResp := cluster_api.GetClusterResponse{}
+	err = json.Unmarshal(response.Body, &clusterResp)
+	if err != nil {
+		return nil, err
+	}
+
+	if clusterResp.CurrentState != cluster_api.TurnedOff {
+		state = "on"
+	} else {
+		state = "off"
+	}
+
+	refreshedState := providerschema.FreeTierClusterOnOff{
+		ClusterId:      types.StringValue(clusterId),
+		ProjectId:      types.StringValue(projectId),
+		OrganizationId: types.StringValue(organizationId),
+		State:          types.StringValue(state),
+	}
+
+	return &refreshedState, nil
+}
+
+func (f *FreeTierOnOff) checkClusterForDesiredStatus(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
path: internal/resources/free_tier_on_off.go
user: login: PaulomeeCb
body: Can you add godocs for why are we doing this?
created_at: 2025-04-15T03:55:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
path: internal/resources/free_tier_on_off.go
user: login: PaulomeeCb
body: Can you add godocs for why are we doing this?
created_at: 2025-04-15T03:56:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
path: internal/resources/free_tier_on_off.go
user: login: SaicharanCB
body: the state file itself has the parameter cluster_id, it is defined by the v4 schema itself, so I'm using the cluster_id only.
created_at: 2025-04-15T07:33:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf(errorMessageWhileClusterOnOffCreation + api.ParseError(err))
+	}
+	return nil
+}
+
+func (f *FreeTierOnOff) retrieveFreeTierClusterOnOff(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+	response, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	//There is no GET endpoint so get the cluster response and check current state
+	clusterResp := cluster_api.GetClusterResponse{}
+	err = json.Unmarshal(response.Body, &clusterResp)
+	if err != nil {
+		return nil, err
+	}
+
+	if clusterResp.CurrentState != cluster_api.TurnedOff {
+		state = "on"
+	} else {
+		state = "off"
+	}
+
+	refreshedState := providerschema.FreeTierClusterOnOff{
+		ClusterId:      types.StringValue(clusterId),
+		ProjectId:      types.StringValue(projectId),
+		OrganizationId: types.StringValue(organizationId),
+		State:          types.StringValue(state),
+	}
+
+	return &refreshedState, nil
+}
+
+func (f *FreeTierOnOff) checkClusterForDesiredStatus(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+
+	var clusterResp cluster_api.GetClusterResponse
+	const timeout = 20 * time.Minute
+	const retryInterval = 3 * time.Second // Added retry delay.
+
+	ctx, cancel := context.WithTimeout(ctx, timeout)
+	defer cancel()
+
+	var desiredState cluster_api.State
+	switch state {
+	case "on":
+		desiredState = cluster_api.Healthy
+	case "off":
+		desiredState = cluster_api.TurnedOff
+	default:
+		return nil, fmt.Errorf("invalid state: %s", state)
+	}
+
+	ticker := time.NewTicker(retryInterval)
+	defer ticker.Stop()
+
+	for {
+		select {
+		case <-ctx.Done():
+			return nil, fmt.Errorf("cluster state check timed out: %w", ctx.Err())
+		case <-ticker.C:
+			response, err := f.Client.ExecuteWithRetry(ctx, cfg, nil, f.Token, nil)
+			if err != nil {
+				return nil, fmt.Errorf("API request failed: %w", err)
+			}
+
+			if err := json.Unmarshal(response.Body, &clusterResp); err != nil {
+				return nil, fmt.Errorf("failed to parse response: %w", err)
+			}
+
+			if clusterResp.CurrentState == desiredState {
+				// Success: Cluster is in desired state.
path: internal/resources/free_tier_on_off.go
user: login: SaicharanCB
body: removed the comment

created_at: 2025-04-15T18:01:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf(errorMessageWhileClusterOnOffCreation + api.ParseError(err))
+	}
+	return nil
+}
+
+func (f *FreeTierOnOff) retrieveFreeTierClusterOnOff(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
+	url := fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/%s", f.HostURL, organizationId, projectId, clusterId)
+	cfg := api.EndpointCfg{Url: url, Method: http.MethodGet, SuccessStatus: http.StatusOK}
+	response, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	//There is no GET endpoint so get the cluster response and check current state
+	clusterResp := cluster_api.GetClusterResponse{}
+	err = json.Unmarshal(response.Body, &clusterResp)
+	if err != nil {
+		return nil, err
+	}
+
+	if clusterResp.CurrentState != cluster_api.TurnedOff {
+		state = "on"
+	} else {
+		state = "off"
+	}
+
+	refreshedState := providerschema.FreeTierClusterOnOff{
+		ClusterId:      types.StringValue(clusterId),
+		ProjectId:      types.StringValue(projectId),
+		OrganizationId: types.StringValue(organizationId),
+		State:          types.StringValue(state),
+	}
+
+	return &refreshedState, nil
+}
+
+func (f *FreeTierOnOff) checkClusterForDesiredStatus(ctx context.Context, organizationId, projectId, clusterId, state string) (*providerschema.FreeTierClusterOnOff, error) {
path: internal/resources/free_tier_on_off.go
user: login: SaicharanCB
body: added the docs
created_at: 2025-04-15T18:01:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
path: internal/resources/free_tier_on_off.go
user: login: SaicharanCB
body: added the docs
created_at: 2025-04-15T18:02:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,10 @@
+auth_token      = "<v4-api-key-secret>"
+organization_id = "<organization_id>"
+project_id      = "<project_id>"
+cluster_id      = "<cluster_id>"
+
+state = "on"
+
+cluster_onoff_ondemand = {
path: examples/free_tier_on_off/terraform.template.tfvars
user: login: SaicharanCB
body: removed it, yeah copying mistake
created_at: 2025-04-15T18:02:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"net/http"
+	"time"
+)
+
+var (
+	_ resource.Resource                = &FreeTierOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierOnOff{}
+)
+
+// FreeTierOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierOnOff creates a new instance of FreeTierOnOff.
+func NewFreeTierOnOff() resource.Resource {
+	return &FreeTierOnOff{}
+}
+
+// Metadata returns the type name for the resource
+func (f *FreeTierOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_on_off"
+}
+
+func (f *FreeTierOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId, state.State.String())
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+func (f *FreeTierOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
+	default:
+		return fmt.Errorf("invalid state value: state must be either 'on' or 'off'")
+	}
+
+	cfg := api.EndpointCfg{Url: url, Method: method, SuccessStatus: http.StatusAccepted}
+	tflog.Info(ctx, url)
+	_, err := f.Client.ExecuteWithRetry(
+		ctx,
+		cfg,
+		nil,
+		f.Token,
+		nil,
+	)
+	if err != nil {
+		return fmt.Errorf(errorMessageWhileClusterOnOffCreation + api.ParseError(err))
path: internal/resources/free_tier_on_off.go
user: login: SaicharanCB
body: the error message is relevant for free tier as well, it is a generic message did not need any specific message related to app services hence I used the same.
created_at: 2025-04-15T18:03:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,318 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
path: internal/resources/free_tier_on_off.go
user: login: SaicharanCB
body: fixed the formatting
created_at: 2025-04-15T18:04:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,275 @@
+# Capella Free Tier Cluster On/Off Example
+
+This example demonstrates how to use the Capella Terraform provider to turn off and on a free-tier cluster
+
+To run, configure your Couchbase capella provider as described in README in the root of this project
+
+# Example Walkthrough
+
+
+In this example, we are going to do the following.
+
+1. CREATE: Swithc the free-tier cluster and assosciated app-service if any to on/off
path: examples/free_tier_on_off/README.md
user: login: PaulomeeCb
body: @SaicharanCB then you should correct this statement, because we do not switch app service to on state.
created_at: 2025-04-18T00:59:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,275 @@
+# Capella Free Tier Cluster On/Off Example
+
+This example demonstrates how to use the Capella Terraform provider to turn off and on a free-tier cluster
+
+To run, configure your Couchbase capella provider as described in README in the root of this project
+
+# Example Walkthrough
+
+
+In this example, we are going to do the following.
+
+1. CREATE: Swithc the free-tier cluster and assosciated app-service if any to on/off
path: examples/free_tier_on_off/README.md
user: login: SaicharanCB
body: Hi @PaulomeeCb , we do switch on the app services to on along with cluster
created_at: 2025-04-18T06:12:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierClusterOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId)
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data.
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+// This function is used to manage the activation state of a free-tier cluster.
+// It switches off/on the free-tier cluster based on the provided input and uses the appropriate HTTP method (POST for "on" and DELETE for "off").
+func (f *FreeTierClusterOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
path: internal/resources/free_tier_cluster_on_off.go
user: login: l0n3star
body: its not common to use HTTP DELETE is used for update
created_at: 2025-04-18T18:31:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
path: internal/resources/free_tier_cluster_on_off.go
user: login: l0n3star
body: not really.  for example if you create new resource and turn off cluster, the only way to turn it off is with update.  
created_at: 2025-04-18T18:35:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierClusterOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId)
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data.
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
path: internal/resources/free_tier_cluster_on_off.go
user: login: l0n3star
body: `DELETE` in this context means destroying on/off resource which is a power off.  There is a DELETE endpoint for power off.  
created_at: 2025-04-18T18:37:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierClusterOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId)
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data.
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
+}
+
+// This function is used to manage the activation state of a free-tier cluster.
+// It switches off/on the free-tier cluster based on the provided input and uses the appropriate HTTP method (POST for "on" and DELETE for "off").
+func (f *FreeTierClusterOnOff) manageFreeTierClusterActivation(ctx context.Context, state, organizationId, projectId, clusterId string) error {
+	var (
+		url    = fmt.Sprintf("%s/v4/organizations/%s/projects/%s/clusters/freeTier/%s/activationState", f.HostURL, organizationId, projectId, clusterId)
+		method string
+	)
+
+	switch state {
+	case "on":
+		method = http.MethodPost
+	case "off":
+		method = http.MethodDelete
path: internal/resources/free_tier_cluster_on_off.go
user: login: SaicharanCB
body: yeah but if we use terraform destroy with delete, we remove the resource from the state file itself and terrform is not handling the resource anymore. I think that is why this way is opted. it is same with the cluster on/off. I found it strange initially but later it made sense.
created_at: 2025-04-18T18:41:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierClusterOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId)
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data.
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
path: internal/resources/free_tier_cluster_on_off.go
user: login: SaicharanCB
body: yeah I get it, I'll update the comments.
created_at: 2025-04-18T18:44:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
+func (f *FreeTierClusterOnOff) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off",
+			"Could not read cluster on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) {
+	var state providerschema.FreeTierClusterOnOff
+	diags := request.State.Get(ctx, &state)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	IDs, err := state.Validate()
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading free-tier cluster on/off details in Capella",
+			"Could not validate the free-tier cluster on/off for cluster "+state.ClusterId.String()+": "+err.Error(),
+		)
+		return
+	}
+	var (
+		organizationId = IDs[providerschema.OrganizationId]
+		projectId      = IDs[providerschema.ProjectId]
+		clusterId      = IDs[providerschema.ClusterId]
+	)
+
+	refreshedState, err := f.retrieveFreeTierClusterOnOff(ctx, organizationId, projectId, clusterId)
+	if err != nil {
+		resourceNotFound, _ := api.CheckResourceNotFoundError(err)
+		if resourceNotFound {
+			tflog.Info(ctx, "resource doesn't exist in remote server removing resource from state file")
+			response.State.RemoveResource(ctx)
+			return
+		}
+		response.Diagnostics.AddError(
+			"Error parsing read free-tier cluster on/off request",
+			"Could not read the cluster details, unexpected error: "+err.Error(),
+		)
+		return
+	}
+
+	diags = response.State.Set(ctx, &refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
+	// Retrieve values from plan
+	var plan providerschema.FreeTierClusterOnOff
+	diags := request.Plan.Get(ctx, &plan)
+	response.Diagnostics.Append(diags...)
+
+	if response.Diagnostics.HasError() {
+		return
+	}
+
+	var (
+		organizationId = plan.OrganizationId.ValueString()
+		projectId      = plan.ProjectId.ValueString()
+		clusterId      = plan.ClusterId.ValueString()
+	)
+
+	if err := f.manageFreeTierClusterActivation(ctx, plan.State.ValueString(), organizationId, projectId, clusterId); err != nil {
+		response.Diagnostics.AddError(
+			"Free-Tier Cluster activation failed",
+			err.Error(),
+		)
+		return
+	}
+
+	refreshedState, err := f.checkClusterForDesiredStatus(ctx, organizationId, projectId, clusterId, plan.State.ValueString())
+	if err != nil {
+		response.Diagnostics.AddError(
+			"Error Reading Capella Free Tier On/Off",
+			"Could not read Capella Free Tier on/off for the cluster: %s "+clusterId+"."+errorMessageAfterClusterOnOffCreation+api.ParseError(err),
+		)
+		return
+	}
+
+	// Set state to fully populated data.
+	diags = response.State.Set(ctx, refreshedState)
+	response.Diagnostics.Append(diags...)
+	if response.Diagnostics.HasError() {
+		return
+	}
+}
+
+func (f *FreeTierClusterOnOff) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+	// Couchbase Capella's v4 does not support a DELETION/destroying resource for free-tier cluster on/off.
+	// Free Tier Cluster on/off can only access the POST and DELETE endpoint which are used for switching the free-tier cluster to on and off state respectively.
+	// https://docs.couchbase.com/cloud/management-api-reference/index.html#tag/Free-Tier/operation/freeTierClusterOn.
path: internal/resources/free_tier_cluster_on_off.go
user: login: SaicharanCB
body: but from terraform perspective deletion means removing the resource from terraform, DELETE api won't hold good for delete() function imo
created_at: 2025-04-18T18:45:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,324 @@
+package resources
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+
+	"github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api"
+	cluster_api "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/api/cluster"
+	providerschema "github.com/couchbasecloud/terraform-provider-couchbase-capella/internal/schema"
+)
+
+var (
+	_ resource.Resource                = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithConfigure   = &FreeTierClusterOnOff{}
+	_ resource.ResourceWithImportState = &FreeTierClusterOnOff{}
+)
+
+// FreeTierClusterOnOff is a struct that represents the free tier on/off status of a cluster.
+type FreeTierClusterOnOff struct {
+	*providerschema.Data
+}
+
+func (f *FreeTierClusterOnOff) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
+	if request.ProviderData == nil {
+		return
+	}
+
+	data, ok := request.ProviderData.(*providerschema.Data)
+
+	if !ok {
+		response.Diagnostics.AddError(
+			"Unexpected Resource Configure Type",
+			fmt.Sprintf("Expected *ProviderSourceData, got: %T. Please report this issue to the provider developers.", request.ProviderData),
+		)
+
+		return
+	}
+
+	f.Data = data
+}
+
+func (f *FreeTierClusterOnOff) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) {
+	// Retrieve import name and save to id attribute
+	resource.ImportStatePassthroughID(ctx, path.Root("cluster_id"), request, response)
+}
+
+// NewFreeTierClusterOnOff creates a new instance of FreeTierClusterOnOff.
+func NewFreeTierClusterOnOff() resource.Resource {
+	return &FreeTierClusterOnOff{}
+}
+
+// Metadata returns the type name for the resource.
+func (f *FreeTierClusterOnOff) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) {
+	response.TypeName = request.ProviderTypeName + "_free_tier_cluster_on_off"
+}
+
+func (f *FreeTierClusterOnOff) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
+	resp.Schema = FreeTierClusterOnOffSchema()
+}
+
+// Create allows to swtich the free-tier cluster on and off.
path: internal/resources/free_tier_cluster_on_off.go
user: login: SaicharanCB
body: I'll update with suitable comment.
created_at: 2025-04-18T18:46:32Z
author_association: CONTRIBUTOR

PR comments:
user: login: SaicharanCB
created_at: 2025-04-15T03:41:10Z
body: > @SaicharanCB I think you should mention `cluster` in the resource, so everywhere it should be `free_tier_cluster_on_off` instead of `free_tier_on_off`, it'll make it more clear.

Hey @PaulomeeCb , since we are also switching off app services as well along with the cluster, so I didn't add the cluster in the name, but on second thought feels adding is better, will add it.
author_association: CONTRIBUTOR
user: login: SaicharanCB
created_at: 2025-04-15T18:04:21Z
body: > Can you add tests for checking what happens when-
> 
> 1. PFT cluster is off but we still try to switch it off.
> 2. PFT cluster is on but we still try to switch it on.

Hi @PaulomeeCb , I have updated the testing doc with these test cases
author_association: CONTRIBUTOR