<aside> <img src="/icons/reorder_gray.svg" alt="/icons/reorder_gray.svg" width="40px" />
</aside>
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.
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 properties tailored to each cloud provider
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
We support intelligent resource renames that complete instantly. Consider this Terraform example
resource "aws_s3_bucket" "example" {
bucket = "main-bucket"
}
// later we would like to rename "example" to "main"
resource "aws_s3_bucket" "main" {
bucket = "main-bucket"
}
Terraform resource rename destroys and recreates the resource! not only that but it takes a lot of time for this to happen
the output:
**# 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:::main-bucket" -> null
- bucket = "main-bucket" -> null
}
# aws_s3_bucket.kite will be created
+ resource "aws_s3_bucket" "kite" {
+ bucket = "main-bucket"
}
Plan: 1 to add, 0 to change, 1 to destroy.
resource Bucket example {
bucket = "logs"
}
// rename "example" to "kite". A simple resource name change is enough
resource Bucket kite {
bucket = "logs"
}
the output:
# DummyResource.example will be renamed to DummyResource.kite
resource DummyResource example -> kite {
bucket = "kite-bucket"
}
Plan: 0 to add, 0 to change, 0 to destroy, 1 to rename.
Notice the -> operator which is used to indicate a resource rename. We detect resource renames so that you can focus on more important things
We use the existing
keyword to reference and import and existing cloud resource into code
existing resource Bucket example {
bucket = "kite-bucket"
}
<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:
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"
}
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'