GCP Service Accounts Explained: Identities for Apps and Automation

Imagine you write a script that reads from BigQuery and writes results to Cloud Storage. It works because it runs as your personal Google account. Six months later, you move to another team. Your account is removed from the project. The script breaks at 3am on a Sunday. The fix is to grant someone else’s account access, but nobody removes that access when they leave either. The cycle repeats.

Service accounts solve this directly. A service account is a non-human identity that belongs to a project, not a person. Your application authenticates as the service account. The service account has exactly the permissions it needs. When team members come and go, nothing breaks. When the application retires, you delete the service account.

The simple explanation

A service account is an identity for your application, not for you. Think of it as an access badge for a piece of software.

In GCP, a service account is a type of principal: an identity that can be granted IAM roles. The key difference from a human account is how it authenticates. No password. No login prompt. When a service account is attached to a compute resource, GCP handles credentials automatically. Your code does not touch credentials at all.

What a service account looks like

Every service account has an email-style identifier. This is the address you use in IAM policy bindings when granting access.

# Service account email format:
service-account-name@project-id.iam.gserviceaccount.com

# Real examples:
backend-api@my-app-prod.iam.gserviceaccount.com
data-pipeline@analytics-project.iam.gserviceaccount.com
deploy-bot@my-app-prod.iam.gserviceaccount.com

From IAM’s perspective, a service account is a principal, the same category as a human user or a Google Group. You grant it roles the exact same way. The identifier backend-api@my-app-prod.iam.gserviceaccount.com tells you the account name (backend-api), the project it lives in (my-app-prod), and that it is a service account (iam.gserviceaccount.com).

Controlling access to a service account

You can also manage who is allowed to use a service account, not just what the service account can do. For example, you can restrict which humans or services are allowed to impersonate it or generate tokens on its behalf. This is separate from the roles the service account holds on other resources.

How service accounts work

Here is what happens when your code calls a GCP API using a service account:

  1. Your workload (a VM, Cloud Run service, Cloud Function) runs with an attached service account.
  2. Your code calls a GCP API, like reading a file from Cloud Storage.
  3. The GCP client library contacts the metadata server (a local endpoint available to every GCP compute resource) and requests a short-lived access token for the attached service account.
  4. GCP issues the token. Your code presents it with the API request.
  5. IAM checks whether the service account has the right role on the target resource. If it does, the action is allowed.
How ADC fits in

Your application code handles none of this directly. GCP client libraries (Python, Go, Node.js, Java) use Application Default Credentials (ADC) to find the right identity automatically. On GCP infrastructure with an attached service account, ADC talks to the metadata server. No files, no environment variables, no credentials in your code. For how ADC behaves during local development, see User Identities vs Service Accounts.

Authentication vs authorisation

Attaching a service account handles authentication: proving who the workload is. The IAM roles granted to that service account handle authorisation: deciding what it is allowed to do. Both are required. Attaching a service account without granting it any roles means the workload can identify itself but cannot perform any actions.

When to use a service account

Any time automated code needs to interact with GCP, it should use a service account. Common situations:

  • Cloud Run or Cloud Functions calling another GCP API. Your service queries Firestore, reads from Cloud Storage, or publishes to Pub/Sub. Attach a service account with only the roles those operations require.

  • A Compute Engine VM accessing GCP resources. The VM reads configuration from Cloud Storage, writes metrics, or calls an API. Attach a service account at VM creation time instead of using the broad default.

  • A CI/CD pipeline deploying infrastructure. Cloud Build, GitHub Actions, or another pipeline needs to push container images, deploy Cloud Run services, or apply Terraform. A service account with deployment-specific IAM roles is the right identity.

  • GKE workloads accessing cloud resources. Pods in a GKE cluster authenticate as a service account via Workload Identity, the Kubernetes-native equivalent of an attached service account.

  • Scheduled jobs and automation. Cloud Scheduler, Cloud Tasks, and Workflows all support running as a service account so each scheduled operation has its own narrowly scoped identity.

Keep roles narrow

In all of these cases, the service account should have the narrowest roles needed for the task. A pipeline that only deploys Cloud Run services does not need Storage Admin or BigQuery access. Grant only what the specific workload actually does.

Service account vs user account

GCP has two main identity types. Knowing when to use each prevents a recurring class of security incidents. For the full breakdown, see User Identities vs Service Accounts.

User accounts are for humans

A user account (a Google Account or Google Workspace account) represents a person. It authenticates with a password and MFA. It is managed outside GCP. Use user accounts when a human is directly accessing GCP: logging into the Console, running gcloud on their machine, or reviewing resources interactively.

Service accounts are for workloads

A service account belongs to a project, not a person. It has no password. When a team member leaves, their user account is deactivated, but service accounts keep running because they are not tied to anyone. Service accounts are the right identity for applications, VMs, pipelines, and anything that runs without a human present.

Never mix these up

Using a personal user account for automation ties your infrastructure to an individual. When that person leaves, jobs break. Using a service account for interactive human access is not possible either: service accounts cannot do browser-based logins. Keep the two identity types separate.

Types of service account

User-managed service accounts

These are the service accounts you create and control. Create one per application or workload, name it clearly after what it does, and grant only the roles that workload requires. This is the kind you will work with most of the time.

# Create a service account for the backend API
gcloud iam service-accounts create backend-api \
  --description="Service account for the backend API service" \
  --display-name="Backend API" \
  --project=my-app-prod

# Grant it a specific role (Storage Object Viewer in this case)
gcloud projects add-iam-policy-binding my-app-prod \
  --member="serviceAccount:backend-api@my-app-prod.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

# List all service accounts in a project
gcloud iam service-accounts list --project=my-app-prod

Google-managed service accounts

When you enable GCP services, Google automatically creates service accounts to allow those services to operate internally. Enabling Cloud Build creates a Cloud Build service account. Enabling Dataflow creates a Dataflow service account. These appear in your project’s IAM policy and are managed by Google; you do not create or rotate their keys.

Review these occasionally

Open IAM in the Console and look for members ending in @cloudservices.gserviceaccount.com or @system.gserviceaccount.com. These are Google-managed. Check that their roles match what the associated service actually needs to do. They often have broader permissions than you might expect.

Default service accounts

When you enable the Compute Engine or App Engine APIs, GCP creates a default service account for the project. When you create a VM without specifying a service account, GCP attaches this default account automatically.

Default service accounts have broad permissions

The default Compute Engine service account is granted roles/editor on the project by default. That is far wider than most VMs need. Instead of accepting the default, create a dedicated service account with only the roles your application requires, then attach that explicitly at VM creation time.

How code authenticates as a service account

There are two approaches. The first is strongly preferred. The second is sometimes unavoidable but carries real risk.

Attached service account (preferred)

If your code runs on GCP infrastructure: a Compute Engine VM, a Cloud Run service, a GKE pod, attach a service account to that compute resource at creation time. The code authenticates automatically via the metadata server, a local endpoint that every GCP compute resource can reach internally. No key file is stored anywhere. GCP refreshes the short-lived token continuously. Your application code does not handle credentials at all.

# Attach a service account to a VM at creation
gcloud compute instances create my-vm \
  --zone=us-central1-a \
  --service-account=backend-api@my-app-prod.iam.gserviceaccount.com \
  --scopes=cloud-platform

# Attach a service account to a Cloud Run service at deploy time
gcloud run deploy my-service \
  --region=us-central1 \
  --service-account=backend-api@my-app-prod.iam.gserviceaccount.com \
  --image=gcr.io/my-app-prod/my-service
Best practice

If your code runs on GCP, always attach a dedicated service account. This eliminates the entire class of credential-leak vulnerability. Credentials live at the infrastructure layer, not in source code, not in environment variables, not in a file on disk.

Service account key files (avoid where possible)

You can download a JSON key file for a service account. Code loads the file to authenticate. This works anywhere, including entirely outside GCP. But that flexibility is also the risk. A key file that reaches the wrong hands grants its full permissions until explicitly revoked.

Key files do not expire

A key created today still works in two years unless you revoke it. If one leaks into a git repository, build log, or screenshot, the clock starts immediately. For a full breakdown of the risks and safer alternatives, see Why Service Account Keys Are Dangerous and Service Account Keys Explained.

# Generate a key file (only when an attached service account is not an option)
gcloud iam service-accounts keys create key.json \
  --iam-account=backend-api@my-app-prod.iam.gserviceaccount.com

# Tell GCP client libraries where to find it
export GOOGLE_APPLICATION_CREDENTIALS="/secure/path/key.json"
Never do this with key files
  • Commit a key file to a git repository, even a private one
  • Hard-code the path or contents in source code
  • Store a key file where other users, services, or containers can read it
  • Share a key file by email or Slack as a way to hand off credentials
Running outside GCP? Use Workload Identity Federation

For workloads running in GitHub Actions, AWS, Azure, or on-premises, Workload Identity Federation exchanges an external identity (a GitHub OIDC token, an AWS IAM role) for a short-lived GCP access token. No key file is created or stored.

Service account impersonation

Impersonation lets you act as a service account temporarily without creating a key file. It is the right way to test what a service account can and cannot do before deploying code that will run as that account in production.

# Run a gcloud command as if you were a specific service account
gcloud storage ls \
  --impersonate-service-account=backend-api@my-app-prod.iam.gserviceaccount.com

# This requires the Token Creator role on the target service account:
# roles/iam.serviceAccountTokenCreator
Safer than downloading a key

When you impersonate a service account, GCP generates a short-lived token scoped to that account’s permissions. The token expires quickly. No permanent credential is created. The permission to impersonate can be granted narrowly and revoked easily, making it fundamentally safer than creating a key file.

For a full guide including how to configure impersonation for CI/CD and local development, see Service Account Impersonation. If you hit permission denied errors after setting up a service account, see Troubleshooting Authentication Errors for the most common causes and fixes.

Best practices

  • One service account per workload. Never share a service account across multiple applications. When you need to revoke or adjust access for one, it will affect all of them.

  • Apply least privilege. Grant only the roles the service account actually needs. A service that reads from Cloud Storage needs roles/storage.objectViewer, not roles/editor. See Principle of Least Privilege for a practical guide.

  • Prefer attached identities over key files. If code runs on GCP, attach a service account to the resource. This removes the entire class of credential-file vulnerability.

  • Avoid long-lived keys. If a key file is unavoidable, treat it as a secret: store it in Secret Manager, audit it regularly, and rotate it on a schedule.

  • Use impersonation for testing. Before deploying code that will run as a service account, use gcloud —impersonate-service-account to verify permissions interactively. No key required.

  • Name service accounts clearly. Use names that reflect what the service account does: backend-api, deploy-bot, data-pipeline. Avoid generic names like service-account-1.

  • Review permissions regularly. Service account roles accumulate. Schedule a quarterly audit of what each service account can access and whether it still needs every role it holds.

Common mistakes

  1. Granting Owner or Editor to a service account. The most common and most damaging mistake. A service account that reads from Cloud Storage should have roles/storage.objectViewer, not roles/editor. Broad roles mean a compromised service account causes broad damage.

  2. Committing a key file to git. This is behind most GCP credential leaks. A developer adds key.json to their project directory, pushes to GitHub, and automated scanners find it within minutes. It happens to experienced engineers. Treat key files as secrets, or better, avoid them entirely.

  3. Sharing one service account across multiple applications. Revoking or adjusting access for one application then affects all of them. A security incident in one application exposes the permissions of every other application sharing that identity. One service account per workload.

  4. Leaving the default Compute Engine service account in place. When you create a VM without specifying a service account, GCP attaches the default, which often has roles/editor on the entire project. Always create a dedicated service account with only the roles your application needs, then attach that explicitly.

  5. Not auditing old keys. Key files do not expire automatically. A key created two years ago and long forgotten still works until explicitly revoked. Audit service account keys regularly with gcloud iam service-accounts keys list and delete any that are no longer in use.

  6. Confusing authentication with authorisation. Attaching a service account to a VM proves who the workload is, but it does not grant any permissions. You must also grant the service account the appropriate IAM roles. If you see permission errors after attaching a service account, the roles are missing. See Troubleshooting Permission Denied Errors.

Frequently asked questions

What is a service account in GCP?

A service account is a special identity for applications, VMs, and automated processes, not for humans. It has an email-style identifier, can be granted IAM roles, and authenticates using short-lived tokens rather than a password. When your code needs to call a GCP API, a service account is the right identity to use.

What is the difference between a service account and a user account in GCP?

A user account represents a human. It authenticates with a password and MFA, and is tied to an individual. A service account represents a workload: an application, a VM, a pipeline. It authenticates without a password, belongs to a project rather than a person, and is the correct identity for anything that runs automatically.

Should I use a service account key file?

Avoid them where possible. Key files are long-lived credentials that can be committed to git, stored insecurely, or stolen. Code running on Compute Engine, Cloud Run, or GKE can authenticate automatically via the attached service account with no key file needed. For external workloads, use Workload Identity Federation instead.

What is service account impersonation?

Impersonation lets you act as a service account temporarily, without creating a key file. Using gcloud with the --impersonate-service-account flag, GCP issues a short-lived token scoped to that account. This is the recommended way to test service account permissions interactively. You need the roles/iam.serviceAccountTokenCreator role on the target account.

Do service accounts have passwords?

No. Service accounts do not use passwords. They authenticate using short-lived tokens issued by the metadata server when attached to a compute resource, or via JSON key files. Because attached authentication requires no stored credential, key files should be avoided wherever possible.

Last verified: 21 March 2026 Cloud services change frequently. Verify details against official documentation before making infrastructure decisions.