TL;DR: A push fires a webhook, GitHub matches it against workflow triggers and queues each job, then assigns jobs to runners advertising a matching label. The runner executes configured steps, including checkout and artifact upload only if requested by the workflow. Knowing that jobs are the unit of scheduling and runners are disposable is what separates an operator's answer from documentation recall.
How to approach it
Split the system into control plane and workers in your first sentence, then walk the lifecycle in order. Expect follow-ups on hosted versus self-hosted runners and artifacts versus cache, so leave threads for both.
A strong answer
The push delivers a webhook event, and GitHub evaluates every workflow file on the pushed ref against its triggers: the on: block filters by event type, branch and path. Matching workflows start a run. GitHub then parses the job graph, the needs: keys, and queues jobs whose dependencies have finished. Jobs are the unit of scheduling. Steps within a job always execute on the same runner and share a working directory, while two jobs may land on entirely different machines, which is why passing data between them requires declared artifacts rather than files on disk.
Runner assignment goes through labels. Hosted pools advertise labels such as ubuntu-latest; a job asking for runs-on: [self-hosted, gpu] waits until a runner carrying both labels is idle. Self-hosted runners register against the repo or organisation and poll for work, so a queued job with no eligible runner sits silently, which is behind a surprising share of "our CI feels slow" reports.
The runner then materialises the environment: checkout, container or toolchain setup, and every uses: action downloaded from its repository at run time. Careful organisations pin third-party actions to a commit SHA, since a mutable tag is remote code execution with a friendly name. Repository secrets become available according to the event and protection rules; a workflow must explicitly reference them as action inputs or environment variables. Keep them out of runner images.
Two consequences of disposability matter in practice. For an ephemeral runner, local state is discarded after the job, so anything worth keeping is uploaded explicitly: actions/upload-artifact writes to run-scoped storage, and a dependent job pulls it down with download-artifact once needs: resolves. Caches are opt-in and use workflow-defined keys; actions/cache does not automatically derive a complete content-addressed build key. Include the dependency lockfile and relevant runtime/platform versions. Without a usable hit, a cold runner installs dependencies again.
Hosted versus self-hosted is the trade interviewers want you to reason through:
| Concern | Hosted runners | Self-hosted runners |
|---|---|---|
| Capacity | Managed pool; quota and capacity can queue jobs | You own provisioning and queueing |
| Cache warmth | Cold each job, pay restore cost | Warm disk possible |
| Trust boundary | Clean VM per job, GitHub-managed | Your network, your credentials nearby |
| Maintenance | Images rotated for you | Patching, disk cleanup, zombie processes |
| Cost shape | Per-minute billing | Fixed hardware, cheaper at volume |
Security settles it for public repositories: prefer hosted runners for untrusted public-fork builds. Checkout alone fetches data; install, build and test steps execute that data as code. A self-hosted design needs single-use isolation, restricted network access and no trusted credentials; ephemerality alone does not protect reachable internal services.
What interviewers probe next
"Your job sat queued for twenty minutes. Where do you look?" Runner availability against the requested labels first, then organisation-level concurrency limits, then whether a job earlier in the needs: chain is stuck.
"Artifacts versus cache?" Artifacts move outputs between jobs and to humans, and expire on retention policy. Cache speeds up repeated work and evicts by inactivity and size. They solve different problems, and swapping them produces confusing pipelines.
"How do you harden workflows triggered by fork PRs?" Read-only token, no secret exposure, actions pinned by SHA, and untrusted code confined to an isolated runner without trusted network or credential access.
Common mistakes
Reciting YAML keywords without the runtime underneath, which reads as documentation recall rather than operating experience.
Assuming state persists between jobs in the same run, then shipping a pipeline that fails only in CI because a file never travelled.
Connecting a persistent self-hosted runner to a public repository and hoping. That is the canonical Actions breach story, and interviewers know it.