cloudfoundry / cloudfoundry/cloud_controller_ng

Proposal: Add lifecycle_type column to apps, droplets, and builds

Open
#5,067 1 comment 0 reactions 1 assignee View on GitHub

@philippthun is already working on this.

Since Jun 30, 2026.

in progress
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:

  1. Expensive list queries - GET /v3/apps?lifecycle_type=docker requires excluding apps from both buildpack_lifecycle_data and cnb_lifecycle_data tables via subqueries
  2. Unnecessary eager loading - Presenters load lifecycle data associations just to determine the type string, even when the full lifecycle data is not needed
  3. 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, and before_create hooks 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 → simple WHERE clause
  • 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.