---
page_title: 'Plugin Development - Framework: Schemas'
description: >-
  How to define a schema using the provider development framework. Schemas
  specify the constraints of Terraform configuration blocks.
---

# Schemas

Schemas specify the constraints of Terraform configuration blocks. They define what fields a provider,
resource, or data source configuration block has, and give Terraform metadata
about those fields. You can think of the schema as the "type information" or
the "shape" of a resource, data source, or provider.

Each concept has its own `schema` package and `Schema` type, which defines functionality available to that concept:

- [Providers](/terraform/plugin/framework/providers): [`provider/schema.Schema`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider/schema#Schema)
- [Resources](/terraform/plugin/framework/resources): [`resource/schema.Schema`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource/schema#Schema)
- [Data Sources](/terraform/plugin/framework/data-sources): [`datasource/schema.Schema`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource/schema#Schema)

During execution of the [`terraform validate`](/terraform/cli/commands/validate), [`terraform plan`](/terraform/cli/commands/plan) and [`terraform apply`](/terraform/cli/commands/apply) commands, Terraform calls the provider [`GetProviderSchema`](/terraform/plugin/framework/internals/rpcs#getproviderschema-rpc) RPC, in which the framework calls the [`provider.Provider` interface `Schema` method](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/provider#Provider.Schema), and the [`resource.Resource` interface `Schema` method](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/resource#Resource.Schema) and [`datasource.DataSource` interface `Schema` method](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework/datasource#DataSource.Schema) on each of the resources and data sources, respectively.

## Version

-> Version is only valid for resources.

Every schema has a version, which is an integer that allows you to track changes to your schemas. It is generally only used when
[upgrading resource state](/terraform/plugin/framework/resources/state-upgrade), to help massage resources created with earlier
schemas into the shape defined by the current schema. It will never be used for
provider or data source schemas and can be omitted.

## DeprecationMessage

Not every resource, data source, or provider will be supported forever.
Sometimes designs change or APIs are deprecated. Schemas that have their
`DeprecationMessage` property set will display that message as a warning when
that provider, data source, or resource is used. A good message will tell
practitioners that the provider, resource, or data source is deprecated, and
will indicate a migration strategy.

## Description

Various tooling like
[terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs) and
the [language server](https://github.com/hashicorp/terraform-ls) can use
metadata in the schema to generate documentation or offer a better editor
experience for practitioners. Use the `Description` property to add a description of a resource, data source, or provider that these tools can leverage.

## MarkdownDescription

Similar to the `Description` property, the `MarkdownDescription` is used to
provide a markdown-formatted version of the description to tooling like
[terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs). It
is a best practice to only alter the formatting, not the content, between the
`Description` and `MarkdownDescription`.

At the moment, if the `MarkdownDescription` property is set it will always be
used instead of the `Description` property. It is possible that a different strategy may be employed in the future to surface descriptions to other tooling in a different format, so we recommend specifying both fields.

## Unit Testing

Schemas can be unit tested via each of the `schema.Schema` type `ValidateImplementation()` methods. This unit testing raises schema implementation issues more quickly in comparison to [acceptance tests](/terraform/plugin/framework/acctests), but does not replace the purpose of acceptance testing.

In this example, a `thing_resource_test.go` file is created alongside the `thing_resource.go` implementation file:

```go
import (
  "context"
  "testing"

  // The fwresource import alias is so there is no collistion
  // with the more typical acceptance testing import:
  // "github.com/hashicorp/terraform-plugin-testing/helper/resource"
  fwresource "github.com/hashicorp/terraform-plugin-framework/resource"
)

func TestThingResourceSchema(t *testing.T) {
  t.Parallel()

  ctx := context.Background()
  schemaRequest := fwresource.SchemaRequest{}
  schemaResponse := &fwresource.SchemaResponse{}

  // Instantiate the resource.Resource and call its Schema method
  NewThingResource().Schema(ctx, schemaRequest, schemaResponse)

  if schemaResponse.Diagnostics.HasError() {
    t.Fatalf("Schema method diagnostics: %+v", schemaResponse.Diagnostics)
  }

  // Validate the schema
  diagnostics := schemaResponse.Schema.ValidateImplementation(ctx)

  if diagnostics.HasError() {
    t.Fatalf("Schema validation diagnostics: %+v", diagnostics)
  }
}
```
