<aside> <img src="/icons/reorder_gray.svg" alt="/icons/reorder_gray.svg" width="40px" />

Navigation

Overview

Install

Architecture


Contact Us

</aside>

What is kite?

Kite is a declarative IaC language designed for consistently provisioning cloud resources. With a single Kite file, you describe the exact infrastructure you need, then reuse that file throughout your development lifecycle to deploy and update environments reliably.

Kite’s clean, concise syntax and strong type safety help you catch errors early, while its modular approach lets you share and reuse code across projects. The result is a streamlined experience that keeps your deployments predictable and maintainable.

Why use it?

Write once, provision anywhere

Define resources once and provision across multiple cloud providers like AWS, GCP, Azure. You can extend a resource or a group of resources using a powerful and flexible feature named mixins

resource Bucket photos {
  name = "my-photos"
}
// resource specific properties
mixin gcp on photos { uniform_bucket_level_access = true }
mixin aws on photos { account_id = "us-east-1" }

// type specific properties on all instances
mixin gcp on Bucket { uniform_bucket_level_access = true }
mixin aws on Bucket { account_id = "us-east-1" }

// properties on all gcp resources
mixin gcp on * { tags = { env: 'prod' } }
// properties on all aws resources
mixin aws on * { tags = { env: 'prod' } }

// general properties for all buckets
mixin Bucket { tags = { env: 'prod' } }

As you can see, you don’t need to refine multiple resources for each cloud provider, just declare one and we’re doing the rest for you

Refactor fearlessly

We provide smart resource renames that don’t take forever to do. Let’s say we have the following terraform example

resource "aws_s3_bucket" "example" {
  bucket = "my-tf-test-bucket"
}

// later we would like to rename "example" to "kite"
resource "aws_s3_bucket" "kite" {
  bucket = "kite-bucket"
}

let’s see how Terraform handle the situation

**# aws_s3_bucket.example** will be destroyed
# (because aws_s3_bucket.example is not in configuration)
- resource "aws_s3_bucket" "example" {
    - arn                         = "arn:aws:s3:::kite-bucket" -> null
    - bucket                      = "kite-bucket" -> null
  }

# aws_s3_bucket.kite will be created
+ resource "aws_s3_bucket" "kite" {
    + bucket                      = "kite-bucket"
  }

Plan: 1 to add, 0 to change, 1 to destroy.

Now let’s see how Kite handles the situation

resource Bucket example {
  bucket = "my-tf-test-bucket"
}

// we would like to rename "example" to "kite". A simple resource name change is enough
resource Bucket kite {
  bucket = "kite-bucket"
}
~ resource DummyResource example -> kite-bucket {
	  bucket = "kite-bucket"
~ }

Plan: 0 to add, 1 to change, 0 to destroy, 1 to rename.

We detect resource renames so that you can focus on more important things

Easy resource imports

We use the existing keyword to reference and import and existing cloud resource into code

existing resource Bucket example {
  bucket = "my-tf-test-bucket"
}

Database-backed state

<aside> 💽

Kite stores state in PostgreSQL instead of a flat files.

</aside>

By using PostgreSQL, we build on a database that’s both powerful and familiar. Teams get enterprise-grade features out of the box, and because PostgreSQL is so widely adopted, your engineers already know how to secure it, back it up, restore it, and query it.

Across cloud providers setting up Terraform state means wiring together buckets, databases, roles, and profiles just to track and lock resources. With Kite, state management is built-in - no extra services to configure, no cloud-specific boilerplate, just a classic database.

Among other features, we believe it helps us in:

Strong typing with clean syntax

Types are enforced without verbose provider prefixes like aws_ or gcp_. Thanks to imports, your code stays short and readable.

import Bucket from aws.s3.Bucket

resource Bucket photos {
  name = "my-photos"
}

Built in constraints

inputs and variables can have validations through decorators or type aliases

@allow(['us-east-1'])
input string location = 'us-east-1'
@minLen
input string name     = 'bucket name'

resource Bucket photos {
  name     = name
  location = location
}

// or use a type alias
type Location = 'us-east-1' | 'us-west-1'
input Location location = 'us-east-1'