cloudfoundry / cloudfoundry/cloud_controller_ng
Proposal: Add lifecycle_type column to apps, droplets, and builds
@philippthun is already working on this.
Since Jun 30, 2026.
- Dominant language
- Ruby
- Stars
- 207
- Forks
- 373
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 56
Description
Problem
Lifecycle type (buildpack, docker, cnb) is not stored directly on apps, droplets, or builds. It is derived at runtime by checking for the existence of associated lifecycle data records:
# Current: checks multiple associations
def lifecycle_type
return 'buildpack' if buildpack_lifecycle_data
return 'cnb' if cnb_lifecycle_data
'docker'
end
This causes:
- Expensive list queries -
GET /v3/apps?lifecycle_type=dockerrequires excluding apps from bothbuildpack_lifecycle_dataandcnb_lifecycle_datatables via subqueries - Unnecessary eager loading - Presenters load lifecycle data associations just to determine the type string, even when the full lifecycle data is not needed
- Implicit semantics - "docker" is the absence of other types, not an explicit value
Proposed Solution
Add a lifecycle_type VARCHAR column (with index) to apps, droplets, and builds tables.
Deployment Strategy (Two Phases, Zero Downtime)
Deploy 1 (PR: #5065):
- Add nullable columns with concurrent index
- Populate for new records via
AppCreate,V2::AppCreate, andbefore_createhooks on droplets/builds - Fallback to association lookup for existing records
- Model validation ensures only valid lifecycle types (buildpack, cnb, docker)
Deploy 2:
- Backfill existing records based on lifecycle data tables
- Make columns non-nullable
- Remove fallback logic
- Optimize
AppListFetcher: subqueries → simpleWHEREclause - Optimize presenters: skip eager-loading lifecycle data for type determination
Impact After Deploy 2
| Area | Before | After |
|---|---|---|
AppListFetcher lifecycle_type filter |
3 subqueries on lifecycle data tables | 1 simple WHERE lifecycle_type = ? |
| Presenters (App, Build, Droplet, Process) | Eager-load lifecycle data associations to determine type | Read column value directly |
| Lifecycle type checks in controllers | Association lookups | O(1) column read |
| Docker type semantics | Implicit (absence of other types) | Explicit column value |
Endpoints That Benefit
Critical: GET /v3/apps with lifecycle_type filter (subquery elimination)
High: All list and detail endpoints for apps, droplets, builds, and processes (presenter eager-load avoidance)
Medium: POST /v3/apps, POST /v3/builds, POST /v3/apps/:guid/actions/start, POST /v3/apps/:guid/actions/restage, POST /v3/spaces/:guid/actions/apply_manifest, POST /v3/droplets/:guid/copy, staging completion (controller-level type checks)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.