Appearance
Pro
Pro adds the workflows a team needs around a production application: preview environments, secure internal services, alarms, auditable production shell and database access, and governance for shared infrastructure. This page separates the capabilities already built from those still planned.
Coming soon
Pro is coming soon.
A preview environment per branch
A preview environment is a temporary copy of a declared environment. Keel creates it for a branch and destroys it when the branch's review closes.
yaml
preview:
enabled: true
base: staging # the environment a preview is derived from
ttl: 72h # how long before 'keel preview reap' destroys it
database: none # none | shared | ownbash
keel preview create --pr 42 # named for the branch: pv-fix-checkout
keel deploy --env pv-fix-checkout # every --env command works on it
keel preview list # what exists, and how long each has left
keel preview destroy --pr 42 # or wait for the TTLKeel synthesises a preview when it resolves the configuration rather than requiring an entry under environments:. That lets deploy, logs, exec, scale, and destroy work against a preview with no further configuration.
The defaults are the inexpensive ones: previews disable the load balancer, put tasks in public subnets, omit the NAT gateway, run one task per service, and add no database unless requested. Override preview.load_balancer or preview.networking independently when an application needs a different tradeoff. keel preview create estimates the environment's cost before provisioning it.
The TTL is active cleanup, not just a timestamp. Closing a pull request triggers destruction, while a scheduled keel preview reap catches anything that workflow misses. When previews are enabled, keel ci workflow generates both jobs.
Teardown is never gated. keel preview destroy and keel preview reap continue to work regardless of licence state, so a lapse cannot leave an account paying for environments it cannot remove.
Alarms
CloudWatch alarms on application health, and where they page.
yaml
alerts:
email: [[email protected]] # or sns_topic_arn: arn:aws:sns:...
# response_time: 2s # p99 — off unless given a number
# http_5xx: 1 # percent of requests (default 1)
# tasks_running: true # no tasks at all (default on)
# database_cpu: 90 # (default 90)The default set is deliberately small: a default threshold exists only where a defensible one does. Response time is not one of those, because "slow" is a property of a particular service rather than of web services, so it stays off until a number is given. An alarm with no delivery configured is refused rather than created.
Two choices reduce false pages. The task alarm fires on no tasks at all rather than on fewer tasks than desired, because autoscaling owns that number and comparing against configuration would alarm on every scale-in. Missing data is treated per alarm: a counter treats absence as healthy, since no requests means no failed requests, while a saturation gauge does not, since a service publishing no CPU is not evidence that it is fine.
The metrics and logs the alarms read are part of the free edition. What Pro adds is the paging.
Internal-only services, behind a login
Network isolation and login form one capability. A private load balancer is only useful to this audience when the people who need the service also have a secure way to reach it.
yaml
services:
admin:
type: web
visibility: internal # a second, private load balancer
port: 4000
auth:
oidc: # Okta, Entra ID, Google, Auth0
issuer: https://acme.okta.com
client_id: 0oa1b2c3d4e5f6g7h8i9
client_secret: ADMIN_OIDC_SECRET # the name of a Keel secret
unauthenticated_paths: ["/webhooks/*"]bash
keel auth oidc discover admin https://acme.okta.comThe load balancer performs the OpenID Connect flow itself and forwards a request only once a session exists, so the application needs no OIDC library and no session store. It receives the identity as request headers, including a signed JWT of the claims. The common alternative is running oauth2-proxy or similar, which is a container to operate and patch.
This is for people who do not have Keel installed: a designer reviewing staging, a product manager, QA, a contractor, or an auditor. They open a URL and sign in with the company identity provider; onboarding can be as small as a group assignment.
Any number of internal services can share one private load balancer, each at its own hostname. Two limits matter. First, an authenticated service has no unauthenticated route: its plain internal name stops resolving so callers inside the VPC cannot bypass the login. Second, authentication is not authorization. Keel verifies that a person signed in; permission to use a particular application remains an identity-provider assignment or a claims check inside the application.
A provisioned identity provider
The configuration above assumes an existing Okta or Entra tenant. For a team without one, Keel can provision the identity provider as well:
yaml
idp:
enabled: true
users: [[email protected], [email protected]]
services:
admin:
auth:
idp: trueKeel creates a Cognito user pool for the environment. No password appears in configuration or OpenTofu state: Cognito sends a temporary password and requires a change at first sign-in. Both identity routes use the same load-balancer action, so moving to Okta later is a keel.yml change rather than an application rebuild.
Deploy on push
bash
keel ci workflow # writes .github/workflows/keel-deploy.ymlThe generated workflow runs keel deploy, the same command a person runs, so the deploy lock, the release-command gate, the history record, the circuit breaker, and preflight all continue to apply. Nothing in Keel listens for a push; GitHub calls Keel.
Deploying is part of Free and will remain so. Pro adds the generated automation that runs a deploy whenever a team member merges.
The role the workflow assumes is the CI identity described in the auth model — OIDC federation, with no long-lived AWS key in CI secrets. That is free, so the role can be created and a workflow written by hand on the free edition.
Operators without AWS keys
An operator signs in through a Cognito pool and receives no general-purpose AWS credential. Their credential can invoke only the Keel control plane, where an authorization grid decides each capability and scope.
bash
keel auth idp add [email protected]
keel auth grants allow [email protected] read --app shop --env staging
keel auth grants allow [email protected] logs --app shop --env stagingEleven independently grantable capabilities cover application reads, logs, resource logs, exec, scale/restart, rollback, config, transcripts, shared platforms, the roster, and the account-wide authorization log. The dashboard's Admin tab manages enrollments and grants and reads allowed and denied decisions.
The IAM route remains the bootstrap and break-glass path. It is not governed by the grid, so a broken control plane cannot prevent an administrator from repairing or removing it. See Operators and The Keel Control Plane.
Recorded exec sessions
yaml
audit:
exec:
record: true
require_reason: true
retention_days: 365bash
keel exec web --reason "investigating the 500s on /checkout"AWS performs the recording rather than the Keel client. It is a property of the ECS cluster, so the same recording configuration applies to interactive sessions opened with Keel or directly with the AWS CLI.
Transcripts are written to a log group of their own that survives keel destroy, so a teardown cannot remove the evidence of what happened before it.
keel audit sessions lists recorded sessions and keel audit transcript <stream> prints one. The separate keel audit decisions log records authorization requests and denials; routine dashboard reads are hidden by default.
This is strong evidence that a session occurred, but it is not a complete record of every keystroke. ECS Exec captures the terminal stream, and a process can suppress its own output. Database statement logs and CloudTrail remain the authoritative record of effects outside that stream.
require_reason is a separate, weaker control because someone who can open a session outside Keel can omit it. Used together, the transcript helps reconstruct the session and the reason records why it was opened through Keel.
Per-person database logins
Without this, every person who reaches the database connects as the shared master user, and the engine's own log cannot attribute a statement to anyone.
yaml
database:
iam_auth: truebash
keel db grant alice # creates the database role "keel-alice"
keel db revoke alice # drops it; IAM access is unchangedEach person then connects as themselves, with no cooperation required from the client. %u in the Postgres log prefix identifies the author of a statement whether it arrived through keel db psql, a tunnel and GUI client, or a migration tool.
A grant creates a login and no privileges. What a person may read remains a schema decision, made in SQL where it can be reviewed. The application keeps the master credential, because an IAM auth token expires in fifteen minutes, so the accurate claim is that human access is attributable while application access remains one identity. Database credentials covers the whole arrangement.
A locked shared platform
Running several applications on one VPC and ECS cluster is part of Free. Pro adds a governance control for the teams that share it:
bash
keel platform lock # 'keel platform set' is refused from here onOnce locked, the only route to changing the shared network is keel platform apply -f against an exported file, so a change to infrastructure that several applications sit inside goes through review. It only matters once more than one person can make that change.
keel platform lock --off is ungated, for the same reason teardown is.
Planned for Pro
These capabilities are defined in the entitlement register but are not built yet. keel license lists the edition they will require:
- Per-app and per-environment IAM roles. Bring scoped direct-IAM sessions beyond the three global levels; operator capability grants already express app and environment scope through the control plane.
- Approval gates and deploy windows. Approval before a production deploy, and hours in which one is refused.
- An intent-level audit trail. A record of who deployed what, where, and what it did — the question auditors ask, and one CloudTrail cannot answer on its own.
- DORA metrics. Deploy frequency, lead time, change failure rate, and time to restore, over more history than a laptop holds.
- IAM Identity Center in place of IAM users.
- Editions overview — the comparison table and how licensing works
- Free — what Pro is added to
- Enterprise — everything here, plus security posture