Verify and clean up
- Lesson 21
- 45 min
- Module 7: Deploy and verify
Lesson 21 of 21 · Build and Deploy Your First APIVerify and clean up
1. Understand the web request
2. Build a small FastAPI service
3. Design a usable contract
4. Document the API with OpenAPI and Swagger UI
5. Explore and test with Postman
6. Test and harden the service
7. Deploy and verify
What you will be able to do
Prove that the deployed API works, with the same checks that you run on your computer. Send a valid request, an invalid one, and a dependency that fails in a controlled way. Then remove everything that you made, so nothing keeps running or waiting to be misused.
Before you startWhat to know and to have ready
What you need to know
- Local and shared values in Postman, from Collections, variables and environments: Local values and shared values.
- The setting
CLASSIFIER_MODE, from Configuration and logging: One place for every setting, and the request ID in the logs, from Configuration and logging: A request ID for every request.
What you need on your computer
- The deployed API, with
API_KEYas a secret, from Publish safely: Step 3: deploy. You need its address, whichfastapi deployprinted. - Its key, which you copied in Publish safely: Step 2: a new key, stored as a secret. If you lost the key, set a new one as in that step, but without
--no-redeploy, so that the app starts again with the new key. - The project folder linked to the app with
.fastapicloud/cloud.json, from Publish safely: Step 1: sign in and create the app. - The collection in
postman, with the/readyrequest, from Publish safely: Guided practice: publish the API. - The Deployed environment in Postman, from Collections, variables and environments: Worked example: two Postman environments.
- The Postman CLI, from Tests and repeatable runs: Run it from the terminal: the Postman CLI.
README.mdin the project, from Environment and first endpoint: Step 5: a README for the project. This lesson adds a section to it.- If your project is missing or broken, copy the snapshot
end-of-m06, the project at the end of Module 6, as in Use a snapshot. Then do the guided practice of Hosting bridge and of Publish safely again. To use the collection in the Postman app, import the files inpostman/(Import). A snapshot has no deployed app and no key.
The steps follow FastAPI Cloud’s documentation and the help of fastapi-cloud-cli 0.26. The Postman CLI steps were tested with version 1.69.0.
A smoke check
Section titled “A smoke check”A smoke check is a short set of requests that you send right after a deployment. It shows that the main paths work: if there is smoke, there is fire. It does not test every detail. That is pytest’s job, before the deployment. It answers one question: is this deployment, on this server, with these settings, working?
Your Postman collection is a good smoke check: it sends a valid ticket, the invalid ones, a request without a key, and checks /health. You only need a Postman environment that points to the server.
Worked example: the Deployed environment
Section titled “Worked example: the Deployed environment”In Postman, Amira opens the Deployed environment from Module 5:
- She sets
baseUrlto her app’s address, for examplehttps://ticket-api.fastapicloud.dev(no/at the end). - She pastes the deployed key into the local value of
apiKey. The shared value stays empty. - She chooses Deployed in the environment selector, and sends Check that the service runs:
200. - She exports the environment as
postman/deployed.postman_environment.json, and checks thatapiKeyis empty in the file. The address is not a secret, so it may stay.
From the terminal, she gives the key to the command without typing it into the command line:
read -s TICKET_API_KEYcurl -s https://ticket-api.fastapicloud.dev/healthpostman collection run postman/ticket-api.postman_collection.json -e postman/deployed.postman_environment.json --env-var "apiKey=$TICKET_API_KEY"$TICKET_API_KEY = Read-Host "API key"curl.exe -s https://ticket-api.fastapicloud.dev/healthpostman collection run postman/ticket-api.postman_collection.json -e postman/deployed.postman_environment.json --env-var "apiKey=$TICKET_API_KEY"read -s TICKET_API_KEYcurl -s https://ticket-api.fastapicloud.dev/healthpostman collection run postman/ticket-api.postman_collection.json -e postman/deployed.postman_environment.json --env-var "apiKey=$TICKET_API_KEY"read -s waits for her to paste the key, and does not show it (-s is “silent”). Read-Host does the same in PowerShell, except that it shows what you paste. Neither one saves the key in the terminal history, because the key is typed as input, not as part of a command.
The curl to /health first wakes the app up. On the Hobby plan, an app that had no requests for a while is stopped (scale to zero). The first request starts it again, which takes a few seconds. Without this, the collection’s test “answers in under 500 ms” can fail on the first request, for a reason that is not a bug.
The run ends like the local run: 8 requests, all tests passed, exit code 0. The same collection, the same tests, a different environment.
A controlled failure, on the server
Section titled “A controlled failure, on the server”The module’s last check: the deployed API must handle a broken dependency as well as the local one. Amira simulates it with the setting from Module 6. Setting a variable redeploys the app with it:
fastapi cloud env set CLASSIFIER_MODE unavailableWhen the new deployment is ready, she calls the two health endpoints and sends a ticket, with her key:
| Request | Expected |
|---|---|
GET /health |
200: the process runs |
GET /ready |
503 {"error":{"code":"classifier_unavailable",...}} |
POST /v1/classify with the key |
503, the same code, with a request ID, and no internal details |
The collection run now fails on Classify a support ticket, with exit code 1, as it must. Then she removes the setting, which redeploys the normal classifier, and runs the collection again: all pass.
fastapi cloud env delete CLASSIFIER_MODERead the platform’s logs
Section titled “Read the platform’s logs”The app writes the same log lines as on your computer, and the platform keeps them (for 1 day on the Hobby plan). To see the recent ones:
fastapi cloud logs --no-follow --since 10mWithout --no-follow, the command keeps showing new lines as they arrive, until you press Ctrl+C. Each request has its line from your middleware, for example:
INFO ticket_api: POST /v1/classify 503 2ms id=5d0b7e1c94aaTo follow up a problem, take the request_id from the error body, and search the logs for it. On macOS and Linux: fastapi cloud logs --no-follow --since 1h | grep 5d0b7e1c94aa. In PowerShell, use Select-String 5d0b7e1c94aa instead of grep.
Document the address
Section titled “Document the address”A deployed API that nobody can find is not finished. Add a short section to the project’s README:
## Deployed practice service
- Address: https://ticket-api.fastapicloud.dev (deleted after the course)- Smoke check:
```sh postman collection run postman/ticket-api.postman_collection.json -e postman/deployed.postman_environment.json --env-var "apiKey=<the key>" ```
- The API key is not in this project. Ask the owner, or set a new one with `fastapi cloud env set API_KEY --secret --value-stdin`.Clean up
Section titled “Clean up”When you have your evidence, remove the practice service. The Hobby plan does not charge you, but a service that nobody watches is still a risk. A key that leaks later still works, and the service keeps using one of your 3 apps.
- Open FastAPI Cloud’s dashboard, select the app, and find the option to delete it in the app’s settings. Confirm.
- In the project folder, remove the link to the deleted app:
fastapi cloud unlink. This deletes.fastapicloud/cloud.json. - In Postman, delete the local value of
apiKeyin the Deployed environment. - Check that the service is gone:
curl -i https://ticket-api.fastapicloud.dev/healthno longer returns200. - In the README, mark the address as deleted.
The key itself no longer works, because the service that checked it is gone. That is the cleanest way to make sure that a practice key can never be misused.
Guided practice: verify and clean up
Section titled “Guided practice: verify and clean up”- Set up the Deployed environment in Postman, and export it into
postman/, without the key. - Wake the app with
/health, then run the collection from the terminal with the Deployed environment. Every test passes. - Set
CLASSIFIER_MODEtounavailable. Check/health(200),/ready(503), and a classify request with the key (503). Run the collection: it fails on the classify request, with exit code1. - Find that classify request in the logs by its request ID.
- Delete
CLASSIFIER_MODE, and run the collection again. Every test passes. - Add the deployed section to the README.
- Delete the app, unlink the folder, and remove the key from Postman. Check that the address no longer answers.
Your turn: a smoke check that you can repeat
Section titled “Your turn: a smoke check that you can repeat”Write a short script, smoke-check.sh (macOS and Linux) or smoke-check.ps1 (Windows), that does steps 2 and 3 of a deployment check in order. It wakes the app with /health, then runs the collection with the Deployed environment. It ends with the collection run’s exit code. The key comes from an environment variable that the person sets before running it, never from the file.
What should the script do if TICKET_API_KEY is not set?
Show one answer for macOS and Linux
#!/bin/sh# Smoke check for the deployed ticket API. Set TICKET_API_KEY first.set -eif [ -z "$TICKET_API_KEY" ]; then echo "Set TICKET_API_KEY first (read -s TICKET_API_KEY)." >&2 exit 2fiBASE_URL="https://ticket-api.fastapicloud.dev"curl -s -o /dev/null "$BASE_URL/health"postman collection run postman/ticket-api.postman_collection.json \ -e postman/deployed.postman_environment.json \ --env-var "apiKey=$TICKET_API_KEY"Without the key, the script stops at once with a clear message and exit code 2 (a wrong command). It does not run the collection and report seven confusing 401 failures. Run it with sh smoke-check.sh. set -e stops the script at the first command that fails. The last command’s exit code becomes the script’s exit code, so a failed check fails the script. The course on CI/CD and safe releases runs a check like this automatically after every deployment.
Common mistake
Only the response-time test fails, and only on the first run
Symptom: the deployed collection run fails one test, answers in under 500 ms, on the first request. Run it again a minute later, and everything passes.
Cause: scale to zero. The app was stopped because nobody used it, and the first request had to wait for it to start. The API is not slow. It was asleep.
Fix:
- Wake the app with a request to
/healthbefore the run, as in the worked example. - Keep a strict time limit for the warm app, because it finds real slowness.
- If you need the first request to be fast too, a paid plan can keep at least one copy of the app running. That is a cost decision, not a code change.
Check your understanding
Why does the smoke check use the Postman collection instead of running pytest against the server?
Show the answer
pytest’s tests use TestClient, which runs the application in memory on your computer. They test the code, not the deployment, and they cannot reach a server. The collection sends real HTTPS requests to the real address, through the platform, with the real settings and secret. That is what can go wrong in a deployment, so that is what a smoke check must test. Both are needed: pytest before the deployment, the collection after it.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Check your understanding
Module check: list the three checks that prove the deployment, with the expected status code of each, and say where each one comes from in the course.
Show the answer
A successful request: POST /v1/classify with the key and a valid ticket gives 200 with the classification (Modules 2 and 6). An invalid request: an empty subject gives 422 with invalid_request and "fields": ["subject"], and a request without a key gives 401 (Modules 3 and 6). A controlled dependency failure: with CLASSIFIER_MODE=unavailable, /ready and classify give 503 with classifier_unavailable and a request ID, while /health stays 200 (Modules 6 and 7). The Postman collection with the Deployed environment shows the first two. The third is shown by setting the variable on the server.
Does your answer have the main points of ours?
Sign in and enroll in the course to save your answers. Every check counts toward the certificate.
Recap
- A smoke check after each deployment answers: does this deployment work? The Postman collection, with a Deployed environment, is that check.
- Give the key to the CLI from input (
read -s,Read-Host), never in a command or a file. - Wake a scaled-to-zero app before a timed test.
- Show a controlled failure on the server with a setting, and remove the setting afterwards.
- Find a request in the platform’s logs by its request ID.
- Document the address. Delete practice services when you are done, and remove their keys.
You built an API from the first request to a deployed, documented, tested and protected service. Next come the two case studies: complete projects on real data that use the whole course. Complete at least one of them for the certificate. Then the final assignment asks you to change your API as a real team would: a new endpoint, from contract to deployment.