Skip to main content
Earlier we covered compositions at a high level — XRs and XRDs. A critical question remains: how does data flow between an XR (Composite Resource) and the composed managed resources? For example, how does spec.size: small on an XR become provider.instanceClass: db.t3.micro on an RDS resource? That programmable mapping and transformation is handled by functions. In this lesson you will:
  • Understand why compositions need programmable logic.
  • Learn the pipeline architecture used for function-based compositions.
  • Inspect the structure and configuration of the function-patch-and-transform input document.
  • Apply patch types and transforms and trace a complete patch-with-transform example end-to-end.
Why use functions? A static Composition that hard-codes every value is impractical for real platforms. Consider the common platform needs:
  • Developers prefer friendly inputs like small or large.
  • The platform maps those friendly values to cloud-specific instance types (db.t3.micro on AWS, db-f1-micro on GCP).
  • The platform composes unique names (e.g., orders-prod) from multiple inputs.
  • Different environments (dev, staging, prod) require different overrides (replica counts, sizes, regions).
Functions provide the programmable logic to implement those mappings. They run in a pipeline: step 1 renders base resources, step 2 applies patches and transforms, and subsequent steps chain additional logic. Each function receives the XR and the accumulated output and passes it to the next function. Typical capabilities include: declarative patches & transforms, conditional logic, and value mapping. Function types The most important Crossplane function types:
A presentation slide titled "Function Types – Choose Your Tool" showing three core function options: 01 function-patch-and-transform, 02 function-go-templating, and 03 function-kcl, each with a brief description of their purpose. The slide is styled with blue gradient buttons and boxed description panels.
There are also useful community-provided functions:
  • function-auto-ready — set the XR Ready status automatically based on composed resource readiness.
  • function-cel-filter — filter resources using a CEL expression.
  • Custom functions — author in Go or Python for special logic.
Pipeline structure and the patch-and-transform input Compositions using functions typically set mode: Pipeline and include a list of pipeline steps. Each step references a function (commonly function-patch-and-transform) and supplies an input document that declares resources and patches. Example pipeline snippet:
Each resource entry under resources contains:
  • name: an identifier used by later patches and pipeline steps.
  • base: a template for the composed managed resource (apiVersion, kind, spec defaults).
  • patches: an array of patch definitions that move data between the XR and the composed resource (either direction).
Patch types Patches define how data flows between the XR, composed resources, and environment-level configuration. Here are the key patch types and their directions: Common examples From XR to resource — single field copy:
From XR to resource — combine multiple fields into a single string (useful for metadata.name):
Resource to XR — surface a managed status value back to the XR:
Environment to resource — copy platform defaults:
Focus recommendation: prioritize mastering FromCompositeFieldPath and CombineFromComposite — they cover most mapping and naming tasks. Transforms Patches move values; transforms mutate those values during the move. Transforms are declared alongside patches and are applied in order. Common transform categories include string transforms, type conversion, and math operations. String transforms
  • Format — build strings from templates:
  • Map — a lookup table (the most common pattern for mapping friendly sizes to provider types):
Type conversion
  • Convert — change the data type (e.g., string -> integer):
Math operations
  • Math — basic arithmetic (useful for unit conversions, e.g., GB -> MiB):
Practice focus: string transforms (Format and Map) and Convert are the most frequently used in real-world compositions. End-to-end example: FromCompositeFieldPath + Map transform This pattern is the bread-and-butter of Crossplane compositions. Flow:
  1. Developer submits an XR with spec.size: "small".
  2. A FromCompositeFieldPath patch reads spec.size.
  3. A map transform converts small -> db.t3.micro.
  4. The final value is written to spec.forProvider.instanceClass on the managed resource.
Patch and transform snippet:
XR input:
Resulting composed managed resource field:
This FromCompositeFieldPath + map transform pattern is the most frequently used mapping pattern — practice it until it feels natural.
Focus first on the declarative function-patch-and-transform patterns: FromCompositeFieldPath and CombineFromComposite, together with string transforms (Format and Map). They solve most real-world mapping and naming needs.
Summary and best practices
  • Use Composition mode: Pipeline with functions when you need programmable composition logic.
  • function-patch-and-transform is the essential, declarative function for most mapping, naming, and conversion work. Its input uses apiVersion: pt.fn.crossplane.io/v1beta1 and kind: Resources.
  • Master FromCompositeFieldPath and CombineFromComposite for XR -> resource mappings and naming.
  • Use Map transforms for friendly-to-provider mappings and Format for string composition.
  • Reserve function-go-templating and function-kcl for scenarios that require more expressive templating or logic.
A presentation slide titled "Key Takeaways" with a blue gradient sidebar and three numbered points. The points summarize: compositions use Pipeline mode with functions; "function-patch-and-transform" is essential; and key patch types are FromCompositeFieldPath and CombineFromComposite.
Links and references

Watch Video