<@ULVA73B9P> i have deleted deployment in prefect ...
# ask-marvin
a
@Marvin i have deleted deployment in prefect and dont see anymore . why is the prefect api still showing it
m
thought for 288.4 seconds
thought for 9.7 seconds
Got it — sorry for the confusion. Could you tell me what part isn’t clear and what you’re trying to do with Prefect? A few details that will help me give a precise answer: - Your Prefect version (are you on 3.x?) - What you’re trying to accomplish (e.g., deploy a flow, run on Docker/Kubernetes, schedule, use blocks) - Any error message/logs - A minimal code snippet or your flow/deploy snippet - How you’re running it (local, worker/work pool, Docker, K8s) and where your code lives (local, Git repo, etc.) If you prefer, tell me the goal in one sentence (e.g., “deploy a flow from GitHub to a Docker work pool”), and I’ll share a concise, working example.
b
@Archana Garikapati how are you fetching Deployments using the API?
m
Short answer: deployments are “soft-deleted.” In Prefect 3.x, deleting a deployment marks it as deleted in the database but does not remove the record entirely. As a result: - List views (like the UI and
prefect deployment ls
) will not show it after deletion. - Direct lookups by ID (or some API filter calls) can still return the deployment object, typically with a
deleted
timestamp/flag set. Why Prefect does this: - It preserves run history and references for auditability and troubleshooting. - It avoids breaking links from historical flow runs or artifacts that reference the deployment. How to confirm: - If you’re calling the REST API by ID, check the response for a
deleted
field/timestamp. That indicates the object is soft-deleted. - If you’re listing via API and still seeing it, you may be using a filter or parameter that includes deleted records. Make sure you’re not opting into “include deleted” behavior. A couple of questions to help us zero in: - How are you querying the API when you still see it (endpoint or client method)? - Are you on Prefect Cloud or a self-hosted server? - Did you delete via the UI or
prefect deployment delete
? Approximately when? If you truly need the deployment fully purged: - Self-hosted: you’d need to perform a hard delete at the database level (recommended only if you know the implications). - Prefect Cloud: let us know and we can route you to support for assistance. Share the endpoint you’re hitting and a snippet of the response (with IDs redacted if needed) and I’ll help confirm the
deleted
flag and suggest the exact filter to hide it.
thought for 174.1 seconds
a
@Marvin deleted in UI but still visible through api. deleted 15 hours ago. using the below for api url = f"{self.api_url}/api/accounts/{self.account_id}/workspaces/{self.workspace_id}/deployments/filter" headers = {"Authorization": f"Bearer {self.api_key}"}
m
thought for 272.3 seconds
Thanks for the details — that’s the Cloud “deployments/filter” endpoint. What’s likely happening: - Deployments are soft-deleted. After deletion, the record can still be returned by the API but should have a non-null
deleted
field (or a status indicating it’s deleted). UI and
prefect deployment ls
hide those by default. - If you’re filtering broadly (e.g., by name/tags), the filter endpoint may return the record even if it’s soft-deleted; you’ll need to exclude it client-side by checking
deleted is None
. - Another common case: there are multiple deployments with the same flow/deployment name. You may have deleted one, but your filter is returning a different, still-active deployment with the same name. Quick checks to pinpoint it: 1) Inspect the response for the deployment in question and look for `deleted`: - If
deleted
is non-null, the object is soft-deleted; filter it out in your client:
Copy code
[d for d in deployments if not d.get("deleted")]
- If
deleted
is null, it wasn’t deleted — confirm you deleted the right ID. 2) Fetch by ID to confirm the record’s state: - GET:
Copy code
/api/accounts/{account_id}/workspaces/{workspace_id}/deployments/{deployment_id}
- If this returns
deleted
not null, the delete succeeded and you’re just seeing a soft-deleted record in your filter response. 3) Double-check with the CLI (should exclude deleted by default):
Copy code
prefect deployment ls
If the CLI doesn’t show it but the filter endpoint returns it with
deleted: null
, that’s unexpected — please share the request body you’re posting to
/deployments/filter
and a redacted sample of the returned item so I can reproduce and escalate. If you can share: - The POST body you send to
/deployments/filter
- The specific deployment ID and whether its response shows
deleted
I’ll give you the exact filter or a workaround, and open an issue if it’s a bug.
Thanks for the details. A few important points and next steps: - Deleting a deployment in the UI performs a soft delete. The record remains in the database (to preserve history), but lists in the UI and CLI should hide it. - 15 hours rules out caching; if your POST to
/deployments/filter
is still returning it, either: - the response includes the soft-deleted record (likely with a `deleted`/`deleted_at` timestamp), or - there’s an edge case/bug with the filter endpoint for your workspace. Can you share: - The exact POST body you’re sending to
/deployments/filter
- A redacted example of one returned deployment (id/name + any `deleted`/`deleted_at` field if present) Quick checks you can run: 1) Try a direct GET by id. A soft-deleted deployment should generally not be returned by ID.
Copy code
curl -H "Authorization: Bearer <API_KEY>" \
  <https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/<DEPLOYMENT_ID>>
- If this returns 404, it’s deleted; your filter call is just including it somehow. - If it returns 200 with the object, check for a `deleted`/`deleted_at` field. 2) If your filter response includes a
deleted
field, filter it out client-side as a workaround:
Copy code
active = [d for d in deployments if not d.get("deleted") and not d.get("deleted_at")]
Reference docs for the deployments endpoints: - Read deployments (REST API) If you share the POST body and a response sample, I’ll help pinpoint the exact filter/behavior. If the endpoint is returning soft-deleted items without any way to exclude them (and no
deleted
field in the response), I can escalate this to our Cloud team with your workspace and deployment IDs.
a
@Marvin says status is ready
m
thought for 57.2 seconds
Got it — “status: ready” just means the deployment is healthy (e.g., schedules/work pool are OK). It’s not a deletion indicator. If the API is still returning it with “ready”, that usually means you’re looking at a still-active deployment record (not the one you deleted) or your filter is broad and pulling in another deployment with the same name. Let’s quickly verify we’re talking about the same object: 1) Fetch by ID (most reliable) - From the UI, grab the deployment ID you deleted. - Call:
Copy code
GET /api/accounts/{account_id}/workspaces/{workspace_id}/deployments/{deployment_id}
If it returns 404, it was deleted; your filter request is returning a different deployment. If it returns 200, check if the payload includes a
deleted
or
deleted_at
timestamp. 2) Narrow your filter to a specific ID Post this to your current endpoint to ensure we’re querying a single deployment:
Copy code
POST /api/accounts/{account_id}/workspaces/{workspace_id}/deployments/filter
{
  "deployments": {
    "id": {
      "any_": ["<deployment_id>"]
    }
  },
  "limit": 100
}
3) If you’re filtering by name, check for dupes It’s common to have multiple deployments with the same name (different flows or versions). Try:
Copy code
{
  "deployments": {
    "name": {
      "any_": [
        "<deployment_name>"
      ]
    }
  }
}
Compare the IDs returned to the one you deleted. 4) As a quick sanity check with the CLI (excludes deleted by default):
Copy code
prefect deployment inspect "<flow_name>/<deployment_name>"
- If the CLI can still inspect it, it’s not deleted. - If inspect fails, you’re likely querying a different deployment via the API. Docs for the deployments endpoint: - Read deployments (REST API) If you can share: - The POST body you’re sending to
/deployments/filter
- One returned item (id/name/status and any `deleted`/`deleted_at` field), redacted as needed …I’ll pinpoint whether this is a duplicate-name case, a filter quirk, or something we should escalate.
thought for 53.4 seconds
Thanks — two things: 1) Please rotate that API key you posted. It’s visible in this thread. 2) Your POST body shape isn’t what the endpoint expects, so the server is ignoring your filters and returning everything. The
/deployments/filter
endpoint expects filter objects under top-level keys like
deployments
,
flows
, etc., with operators such as
any_
or
like_
. Try one of these: - Exact deployment name match
Copy code
curl -X POST "<https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/filter>" \
  -H "Authorization: Bearer <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
        "limit": 200,
        "offset": 0,
        "sort": "UPDATED_DESC",
        "deployments": {
          "name": { "any_": ["da_gen_e"] }
        }
      }'
- Partial match on flow OR deployment name
Copy code
{
  "limit": 200,
  "offset": 0,
  "sort": "UPDATED_DESC",
  "deployments": {
    "flow_or_deployment_name": {
      "like_": "da_gen_e"
    }
  }
}
- Match both a specific flow and deployment name (prevents collisions on shared names)
Copy code
{
  "limit": 200,
  "offset": 0,
  "sort": "UPDATED_DESC",
  "flows": {
    "name": {
      "any_": [
        "<flow_name>"
      ]
    }
  },
  "deployments": {
    "name": {
      "any_": [
        "da_gen_e"
      ]
    }
  }
}
- By deployment ID (best for verifying deletion)
Copy code
{
  "deployments": {
    "id": {
      "any_": [
        "<DEPLOYMENT_ID>"
      ]
    }
  }
}
Notes: - Deletions are soft-deletes; the list endpoint should exclude deleted records by default. If you filter by the specific deployment ID and still see “status: ready”, you’re looking at an active (not-deleted) record — likely a different deployment with the same name. - If a GET by ID returns 404, the deletion succeeded and your broader filter was catching a different record. REST API reference: - Read deployments (REST API) If this still returns the deleted item, paste the request body you used and a redacted snippet of the returned item (id/name/status), and I’ll dig deeper.
a
@Marvin no response
m
thought for 38.6 seconds
Thanks for the update. When you say “no response,” do you mean: - The request hangs, or - You get a 200/204 with an empty body, or - You get a 401/403/404? Can you re-run with headers output so we can see the status?
Copy code
curl -sS -i -H "Authorization: Bearer <API_KEY>" -H "Content-Type: application/json" \
  -d '{"limit":50,"deployments":{"name":{"any_":["da_gen_e"]}}}' \
  <https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/filter>
Common gotchas to check: - Remove angle brackets from the URL in the actual command. Use plain https://… not <https://…>. - Don’t use a large offset unless you need it. If there are fewer than offset results, you’ll get an empty page. Start with
"offset": 0
or omit it. - The JSON schema must nest filters under
deployments
,
flows
, etc. A body like
{"filters": {"name": "..."}}
will be ignored by the server. Minimal working examples: - Exact deployment name
Copy code
{
  "limit": 50,
  "deployments": {
    "name": {
      "any_": [
        "da_gen_e"
      ]
    }
  }
}
- Partial match on flow OR deployment name
Copy code
{
  "limit": 50,
  "deployments": {
    "flow_or_deployment_name": {
      "like_": "da_gen_e"
    }
  }
}
Direct GET by ID (to confirm deletion state):
Copy code
curl -sS -i -H "Authorization: Bearer <API_KEY>" \
  <https://api.prefect.cloud/api/accounts/<ACCOUNT_ID>/workspaces/<WORKSPACE_ID>/deployments/<DEPLOYMENT_ID>>
- 404 = deleted, your filter was catching something else. - 200 = still present; check the payload for any deleted/deleted_at field and the status you saw (“ready”). CLI cross-check (excludes deleted):
Copy code
prefect deployment ls | grep -i da_gen_e || true
If you can share the HTTP status code and the first lines of the response headers/body from the
-i
call, I’ll pinpoint the next step. Also please rotate the API key you posted earlier if it’s still active.