<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay" -->

---
title: Build a Terraform provider for your side project's API...
description: Building a Terraform provider for a side project's API is more approachable than it seems. Using the Terraform Plugin Framework (not the older SDKv2), a...
canonical: https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Build a Terraform provider for your side project's API (it's smaller than you think) | daily.dev
og:description: Building a Terraform provider for a side project's API is more approachable than it seems. Using the Terraform Plugin Framework (not the older SDKv2), a...
og:url: https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay
og:image: https://api.daily.dev/og/posts/7Jl3aCGAy.png
og:image:alt: Build a Terraform provider for your side project's API (it's smaller than you think)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a Terraform provider for your side project's API (it's smaller than you think)

**[Awesome Go](https://daily.dev/sources/awego)** · [@devopsdaily](https://daily.dev/devopsdaily) · 4 min read · 0 upvotes · 0 comments

## Summary

Building a Terraform provider for a side project's API is more approachable than it seems. Using the Terraform Plugin Framework (not the older SDKv2), a provider is a Go module with three components: a provider type for configuration, resources implementing CRUD operations, and data sources for read-only lookups. Key challenges include handling state drift correctly in the Read function, managing sensitive values like one-time API keys, and implementing ImportState for existing resources. Publishing to the Terraform Registry requires a properly named repo, GoReleaser-built binaries, GPG signing, and registry registration. A working reference implementation is the open-source SMTPfast provider, which can be built in roughly a weekend for a v0 with two resources.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://dev.to/devopsdaily/build-a-terraform-provider-for-your-side-projects-api-its-smaller-than-you-think-5bg8>

## Questions this post answers

### Should I use the Terraform Plugin Framework or SDKv2 to build a new provider in Go?

Use the Terraform Plugin Framework (terraform-plugin-framework) rather than the older SDKv2 for a new provider. It is the maintained path, strongly typed, and less magical than SDKv2, structuring a provider around a provider type, resources implementing Create/Read/Update/Delete, and read-only data sources.

_daily.dev surfaces practical framework comparisons for developers deciding how to structure a new Terraform provider._

### How do I avoid Terraform showing a diff on every plan for a custom provider resource?

Unexpected diffs on every plan usually mean the Read function is not mapping every declared attribute from the live API response back into state. Terraform's core job is comparing desired state to real state, so Read must fetch and set every schema attribute every time, or stale or ignored server-side changes will surface as mysterious drift.

_developers debugging provider drift can find grounded fixes like this on daily.dev._

### How should a Terraform provider handle an API key that the API only returns once at creation?

Store the secret in Terraform state at create time, mark the schema field Sensitive: true, and never attempt to re-read it on subsequent Read calls since the API will not return it again. Document that state files must be treated as secrets, since they already should be regardless of this pattern.

_daily.dev helps developers building provider integrations track patterns for handling sensitive API values._

## Similar posts on daily.dev

- [How to Get Started with Terraform](https://daily.dev/posts/how-to-get-started-with-terraform-mojbh4put) · freeCodeCamp · 1 upvotes · 0 comments
- [Terraform Private Registry: Setup, Publishing & Best Practices](https://daily.dev/posts/terraform-private-registry-setup-publishing-best-practices-efaucd7eq) · Spacelift · 0 upvotes · 0 comments
- [Terraform for developers: a complete beginner's guide](https://daily.dev/posts/terraform-for-developers-a-complete-beginner-s-guide-inhdlixdl) · Flavio Copes · 5 upvotes · 2 comments
- [Terraform Google Cloud Provider 7.0 Reaches General Availability](https://daily.dev/posts/terraform-google-cloud-provider-7-0-reaches-general-availability-dkyqrh1ev) · InfoQ · 1 upvotes · 0 comments
- [How Terraform Works](https://daily.dev/posts/how-terraform-works-m4paeflla) · System Design Codex · 35 upvotes · 0 comments

---

Tags: [#golang](https://daily.dev/tags/golang), [#terraform](https://daily.dev/tags/terraform), [#iac](https://daily.dev/tags/iac)

[View this post on daily.dev](https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Build a Terraform provider for your side project's API (it's smaller than you think)","url":"https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay"},"datePublished":"2026-08-05T07:19:26.191Z","dateModified":"2026-09-14T09:00:41.771Z","description":"Building a Terraform provider for a side project's API is more approachable than it seems. Using the Terraform Plugin Framework (not the older SDKv2), a...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/6dd265e1bdc0f991019c1b61a2ec2c27?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/6dd265e1bdc0f991019c1b61a2ec2c27?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Awesome Go","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Person","name":"DevOps Daily","url":"https://daily.dev/devopsdaily","image":"https://avatars.githubusercontent.com/u/212527239?v=4","description":"The latest news, tutorials, and guides for DevOps professionals.","interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":60}},"commentCount":0,"discussionUrl":"https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"golang,terraform,iac","timeRequired":"PT4M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Awesome Go","item":"https://daily.dev/sources/awego"},{"@type":"ListItem","position":3,"name":"Build a Terraform provider for your side project's API (it's smaller than you think)"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/build-a-terraform-provider-for-your-side-project-s-api-it-s-smaller-than-you-think--7jl3acgay#faq","mainEntity":[{"@type":"Question","name":"Should I use the Terraform Plugin Framework or SDKv2 to build a new provider in Go?","acceptedAnswer":{"@type":"Answer","text":"Use the Terraform Plugin Framework (terraform-plugin-framework) rather than the older SDKv2 for a new provider. It is the maintained path, strongly typed, and less magical than SDKv2, structuring a provider around a provider type, resources implementing Create/Read/Update/Delete, and read-only data sources. daily.dev surfaces practical framework comparisons for developers deciding how to structure a new Terraform provider."}},{"@type":"Question","name":"How do I avoid Terraform showing a diff on every plan for a custom provider resource?","acceptedAnswer":{"@type":"Answer","text":"Unexpected diffs on every plan usually mean the Read function is not mapping every declared attribute from the live API response back into state. Terraform's core job is comparing desired state to real state, so Read must fetch and set every schema attribute every time, or stale or ignored server-side changes will surface as mysterious drift. developers debugging provider drift can find grounded fixes like this on daily.dev."}},{"@type":"Question","name":"How should a Terraform provider handle an API key that the API only returns once at creation?","acceptedAnswer":{"@type":"Answer","text":"Store the secret in Terraform state at create time, mark the schema field Sensitive: true, and never attempt to re-read it on subsequent Read calls since the API will not return it again. Document that state files must be treated as secrets, since they already should be regardless of this pattern. daily.dev helps developers building provider integrations track patterns for handling sensitive API values."}}]}
```

