1---
2title: How objects are managed
3description: How Alchemy applies, orders, prunes, and deletes Kubernetes objects, including server-side apply and field ownership, drift, replacement, unreachable clusters, and adoption.
4---
5
6Every Kubernetes resource in Alchemy turns into one or more
7Kubernetes objects. That includes
8[`Deployment`](/kubernetes/workloads/deployments),
9[`Job`](/kubernetes/workloads/jobs),
10[`Manifest`](/kubernetes/objects/manifests), and
11[`HelmChart`](/kubernetes/objects/helm-charts). This page describes
12what happens to those objects across deploys.
13
14- `Deployment` creates a ServiceAccount, a Deployment, and a Service.
15- `Job` creates a ServiceAccount and a Job or CronJob.
16- `Manifest` creates the one object in `manifest`.
17- `HelmChart` creates every object in the render, plus the Namespace
18 when `createNamespace` is set.
19
20## Server-side apply
21
22Alchemy writes objects with Kubernetes
23[server-side apply](https://kubernetes.io/docs/reference/using-api/server-side-apply/)
24under the field manager `alchemy`, with `force` enabled. Each apply
25sends the complete desired object, and the API server merges it:
26
27- **Alchemy owns the fields it sends.** Forcing means a conflicting
28 value set by another manager is overwritten, and Alchemy becomes
29 that field's owner. Another manager might be `kubectl edit` or
30 another tool.
31- **Fields Alchemy stops sending are removed.** The exception is a
32 field that another manager also set.
33- **Fields Alchemy never sends are left alone.** Controllers can
34 keep writing `status`, autoscalers can manage fields Alchemy
35 doesn't set, and annotations added by other tools survive.
36
37This has one consequence for autoscaling. If a
38HorizontalPodAutoscaler manages a Deployment's replicas, Alchemy's
39`replicas` value (default `1`) still overwrites them on each apply.
40Write the workload as a [Manifest](/kubernetes/objects/manifests)
41without `spec.replicas` when an autoscaler should own the count.
42
43## Apply and delete order
44
45Within one resource, Alchemy applies objects in dependency order.
46Namespaces come first, then CustomResourceDefinitions, then
47ServiceAccounts, ConfigMaps and Secrets, Services, workloads, and
48finally any other kind. Deletes run in the reverse order. Objects at
49the same level are applied in parallel.
50
51Across resources, the order comes from Output references. A
52Deployment whose `namespace` is `ns.name` deploys after the `ns`
53Manifest and is destroyed before it. Resources that don't reference
54each other deploy in parallel.
55
56## Pruning
57
58Alchemy records every object each resource applied. An update can
59produce a different set. For example, a chart's new version drops a
60template, a Job's spec changes its name, or a Deployment moves
61namespace. Alchemy then deletes the objects that are no longer in the
62set before applying the new ones.
63
64Deletes use background propagation, so a deleted Job takes its pods
65with it and a deleted Deployment takes its ReplicaSets.
66
67## When objects are applied
68
69Alchemy applies a resource's objects when the resource is created or
70updated. A resource updates when its props change. It also updates
71when the content of its image source changes. An image source is a
72`context` directory, a bundled `main` program, or a local chart
73directory.
74
75A deploy with no changes applies nothing. Edits made out of band,
76such as `kubectl scale` or `kubectl edit`, stay in place until the
77resource is next applied. To converge everything back to your
78program, force an apply of every resource:
79
80```sh
81alchemy deploy --force
82```
83
84[`alchemy drift`](/cli/drift) detects objects deleted out of band,
85such as a Manifest's object or the ServiceAccount of a Deployment or
86Job. It reports the resource as missing, and
87`alchemy drift --repair` recreates it. It doesn't compare object
88fields, and a HelmChart is only checked for a reachable cluster.
89
90## Replacement
91
92A resource is replaced when its identity changes:
93
94- `Deployment` identity is its cluster and namespace.
95- `Job` identity is its cluster and namespace.
96- `Manifest` identity is its cluster, `apiVersion`, `kind`, `name`,
97 and `namespace`.
98- `HelmChart` identity is its cluster, release name, and namespace.
99
100Replacement creates the new generation first, then deletes the old
101one. Sometimes both generations contain an object with the same name
102in the same place. This happens when the same cluster is reached
103through a different connection, or when a chart object's name
104ignores the release name. Deleting the old generation then removes
105the object the new one just applied. Run `alchemy deploy --force`
106after such a change. See
107[Move a resource to another cluster](/kubernetes/clusters/connecting#move-a-resource-to-another-cluster)
108and [Helm charts](/kubernetes/objects/helm-charts#release-name-and-namespace).
109
110## Deploys don't wait for readiness
111
112Applying succeeds as soon as the API server accepts the objects. A
113Deployment's pods may still be pulling images, and a Job may still
114be running or failing. The one exception is a `LoadBalancer` Service,
115whose deploy waits up to about three minutes for an address. Use
116`kubectl rollout status`, a smoke-test
117[Job](/kubernetes/workloads/jobs), or your own health checks to
118gate on readiness.
119
120## Transient errors
121
122Applies retry for about a minute on API server errors (5xx),
123throttling (429), and authentication or authorization failures (401
124and 403). The 401 and 403 errors are common for a few seconds after
125a hosted cluster or its access grants are created. Validation errors
126such as 422 fail immediately with the API server's message.
127
128## Destroy and unreachable clusters
129
130`alchemy destroy` connects to each resource's cluster using the
131connection stored in state and deletes its objects. What happens
132when the cluster can't be reached depends on why:
133
134- **The cluster is gone.** The cluster's platform reports that it
135 was deleted. Its objects went with it, so Alchemy treats them as
136 deleted. Alchemy still removes any cloud resources the platform
137 created for the workload. On EKS, those are the ECR repository and
138 the Pod Identity role.
139- **The cluster is unreachable.** This covers a kubeconfig cluster
140 that's stopped, or a network problem. `Deployment` and `Job` skip
141 their in-cluster objects and still remove adapter-owned cloud
142 resources. `Manifest` and `HelmChart` fail so you can retry once
143 the cluster is back.
144
145Deleting an object that's already gone is not an error, so destroy
146can be re-run safely.
147
148## Adoption and listing
149
150Kubernetes objects carry no Alchemy ownership marker, so Alchemy
151doesn't enumerate or adopt existing objects. Applying a Manifest or
152chart whose objects already exist takes over their fields through
153server-side apply. From then on, Alchemy manages and deletes them
154like objects it created.
155
156## Where next
157
158- **[Cluster adapters](/kubernetes/clusters/cluster-adapters).** The
159 platform layer behind `connect`, images, and identity.
160- **[Resource lifecycle](/infrastructure-as-code/resource-lifecycle).**
161 How Alchemy plans creates, updates, and replacements across all
162 providers.