TL;DR: Prometheus scrapes an HTTP endpoint on each target every 15 to 60 seconds and stores what it finds. Targets are found through service discovery, not configured by hand. Anything that cannot expose an endpoint gets an exporter; anything that exits before a scrape gets a pushgateway, and that is the only place push belongs.
How to approach it
State the pull model in the first sentence and then derive the rest from it, because service discovery, the health signal and the short-lived-job problem are all consequences of it. If you are asked to compare pull and push, avoid the symmetric non-answer: say what pull buys and name the one case where it does not work.
A strong answer
Your service exposes an HTTP endpoint, conventionally /metrics, returning plain text:
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",status="200"} 48271
http_requests_total{method="GET",status="500"} 13
process_resident_memory_bytes 5.2428e+07
Prometheus requests that page from every target on an interval, parses it, and appends each sample with a timestamp. The application does not send anything and holds no connection. It just keeps counters in memory and renders them when asked.
Targets come from service discovery rather than a static list. In Kubernetes, Prometheus watches the API server and finds pods and services by label or annotation, so a new deployment is scraped automatically and a deleted one stops being scraped. On cloud VMs it discovers by tag. Maintaining a target list by hand is the thing service discovery exists to avoid, and a setup that still does is a setup that will monitor the wrong fleet within a month.
Exporters cover everything that cannot expose the format itself. node_exporter for host CPU, memory, disk and network. postgres_exporter for a database. blackbox_exporter for probing a URL from outside. An exporter is a small process that translates something's native statistics into the Prometheus format on an HTTP endpoint, so from Prometheus's point of view it is an ordinary target.
What the pull model gives you, concretely. Prometheus records up{job="api"} for every scrape, so a target that stops responding is immediately visible as a metric you can alert on, and that is free health checking you did not write. The monitoring system controls the rate, so a misbehaving application cannot flood it. And you can point a browser at /metrics and see exactly what the monitoring sees, which makes debugging trivial compared with a system where data disappears into a pipeline.
The case it does not handle is a job that exits before anyone scrapes it. A nightly batch job running for ninety seconds may never be scraped at all. That is what the pushgateway is for: the job pushes its final metrics to a gateway that holds them, and Prometheus scrapes the gateway. Use it only for that. It is a common mistake to route ordinary service metrics through a pushgateway, which breaks the up health signal, makes the gateway a single point of failure, and leaves stale metrics behind forever because the gateway keeps serving the last value until something deletes it.
One detail on the data model: a metric is a name plus labels, and every distinct label combination is its own time series. That is why putting a user ID or a request ID in a label is the standard way to destroy a Prometheus instance, and it is behind most "Prometheus memory exploded" incidents.
What interviewers probe next
"What happens if a scrape is missed?" A gap. Prometheus marks the series stale after a few missed intervals rather than interpolating, so a graph shows a break and rate() over that window is computed from what exists. Data is not recovered retroactively.
"How does it scale past one server?" Shard by scrape target, then use remote write into a long-term store like Thanos, Mimir or Cortex for global query and retention. A single Prometheus is deliberately simple and holds everything in local storage with no clustering.
"Push or pull, which is better?" Pull for services you run, because of discovery and the free liveness signal. Push where the source is ephemeral or cannot be reached, which is why OpenTelemetry's collector uses push and why the two models coexist without contradiction.
Common mistakes
Routing normal service metrics through a pushgateway, which loses the up signal and leaves stale series behind.
Maintaining static target lists instead of using service discovery, so the monitoring drifts from the fleet.
High-cardinality labels such as user or request identifiers, which multiply series and exhaust memory.
Assuming a missed scrape is backfilled later. The gap is permanent.