Skip to content

Local Development

When you're developing a service and want AAT's integration tests to hit your local instance instead of the shared environment, drop a .aat-overrides.yaml file in your project directory. AAT auto-discovers it on every run — no flags needed.

Quick Setup

  1. Create a .aat-overrides.yaml file in your project root (next to aat-project.yaml):

    overrides:
      - match: searchFlights
        baseUrl: http://localhost:8080
    
  2. Run normally — the override is picked up automatically:

    aat run plan smoke-test
    # aat: auto-discovered overrides: /path/to/project/.aat-overrides.yaml
    # aat: override: searchFlights
    

Add .aat-overrides.yaml to your project's .gitignore so it isn't committed (the shop example's .gitignore already lists it).

Tip: The overlay file also supports top-level auth and headers fields that apply to all API calls. See the examples below.

Common Scenarios

Route one node to localhost

The simplest case — send traffic for a single API operation to your local service:

overrides:
  - match: createOrder
    baseUrl: http://localhost:3000

Disable auth for local dev

Your local service probably doesn't need OAuth tokens:

overrides:
  - match: createOrder
    baseUrl: http://localhost:3000
    auth:
      type: none

Different path structure on local service

If your local service uses a different URL path than production:

overrides:
  - match: createOrder
    baseUrl: http://localhost:3000
    pathRewrite:
      strip: /api/v2
      prefix: /v1

Override all nodes matching a pattern:

overrides:
  - match: "commit*"
    baseUrl: http://localhost:9090

Mix local and remote

Override only the nodes you're working on — everything else stays on the shared environment:

overrides:
  - match: createOrder
    baseUrl: http://localhost:3000
    auth:
      type: none
  - match: updateOrder
    baseUrl: http://localhost:3000
    auth:
      type: none

Use different credentials for the whole run

When the environment you're testing against requires different auth than the base env.yaml, add a top-level auth block. This replaces the environment auth for all API calls, not just matched overrides:

auth:
  type: oauth2
  tokenUrl: https://auth.staging.example.com/token
  credentials:
    username:
      source: env
      var: STAGING_USERNAME
    password:
      source: env
      var: STAGING_PASSWORD
    clientId:
      source: env
      var: STAGING_CLIENT_ID
    clientSecret:
      source: env
      var: STAGING_CLIENT_SECRET

overrides:
  - match: myService
    baseUrl: http://localhost:3000

Add transaction-level headers

Headers at the top level are merged into every request, useful for access-group tokens or other cross-cutting headers. They win over environment headers, plan headers, template headers, and the auth credential, on every route:

headers:
  X-Access-Group: my-group-id
  X-Debug: "true"

overrides:
  - match: myService
    baseUrl: http://localhost:3000

Force a negative case for depth testing

Overlays can mutate individual input values and declare expectFailure for matched nodes. This is handy when you want to rerun a normal plan as a negative test — no edits to the plan itself:

overrides:
  - match: createOrder
    values:
      productId: ""       # force a validation error
    expectFailure:
      status: [400]

With that overlay active, the existing plan runs as-is, but createOrder receives an empty productId and the step passes only if the server responds with 400. See Environments: Input-Value and Expected-Failure Overrides for precedence rules and Plans: Mutations for codifying a whole negative suite in the plan itself.

Target a different backend when running locally

If your local service talks to a different backend than the project default (e.g. the project defaults to pp pre-prod, but your locally-running service hits dev backend resources), name the backend in the overlay:

environment: dev             # selects the dev env from env.yaml
overrides:
  - match: "*"
    baseUrl: http://localhost:8080

Now aat run plan ... picks up the dev environment automatically whenever this overlay is active, and logs aat: using environment "dev" from overlay /path/to/project/.aat-overrides.yaml so the choice is visible. Passing --env pp on the command line (or setting AAT_ENV_NAME) still wins, so the project default is never hidden from you. When both an explicit --overlay file and .aat-overrides.yaml set environment:, the explicit file's value is used.

Top-level environment, auth, headers, and overrides can all be combined in a single file. See Environments: Overlay Files for the full reference.

How It Works

Discovery

AAT walks up from your current working directory looking for .aat-overrides.yaml (or aat-overrides.yaml without the dot; the dotfile wins when a directory has both), the same way it finds aat-project.yaml. The first file found wins. Like every project file, it is decoded strictly: an unknown key is an error. This means you can place the file:

  • In the project root (most common)
  • In a subdirectory for scope-specific overrides
  • In a parent directory to apply across multiple projects

Priority Chain

Override entries are registered from these sources, in this order:

  1. env.yaml overrides: section (permanent, shared)
  2. .aat-overrides.yaml (auto-discovered, personal)
  3. --overlay flag (explicit overlay file)
  4. --override flag (CLI one-off)

When a node matches more than one entry, two rules decide which applies:

  • Exact names beat globs. An entry with match: createOrder always wins over match: "create*" for createOrder, no matter which source each came from.
  • Within the same kind, the last registered wins. A glob in .aat-overrides.yaml beats a glob in env.yaml; an exact name from --override beats the same exact name in any file.

So a personal match: "*" in .aat-overrides.yaml really does redirect everything that env.yaml only routed by glob, while an exact-name entry in env.yaml still pins that one node unless you override it by exact name too. The same rules apply to values: and expectFailure: entries (see Environments: Input-Value and Expected-Failure Overrides).

Environment selection has its own chain: --env flag, then AAT_ENV_NAME, then environment: from the --overlay file, then environment: from .aat-overrides.yaml, then the manifest's defaultEnvironment (only for the environment file the manifest names, not one given with --env-config). A single-environment file ignores all of these except --env.

Transaction-level auth follows a separate chain (later entries replace earlier ones):

  1. env.yaml auth: — base environment credentials
  2. .aat-overrides.yaml auth: — auto-discovered overlay
  3. --overlay file auth: — explicit overlay
  4. Plan-level auth: — per-plan override

Logging

AAT always logs when it finds a .aat-overrides.yaml so you know what's active:

aat: auto-discovered overrides: /path/to/project/.aat-overrides.yaml

Keeping It Clean

Git

AAT does not create a .gitignore for your project, so add .aat-overrides.yaml to it yourself. The AAT repository and the shop example (aat-sandbox init) already ignore it.

CI/CD

For CI pipelines or clean runs where you want to guarantee no local overrides are applied:

aat run batch --no-auto-overrides

The --no-auto-overrides flag is available on aat run plan, aat run batch, and aat prompt.

Existing Alternatives

.aat-overrides.yaml is the recommended approach for ongoing local development. For other scenarios:

  • --override NODE=URL — one-off overrides on the command line, good for quick experiments; each is equivalent to a match: NODE entry with that baseUrl, so it keeps the environment headers and auth
  • --overlay FILE — explicit overlay file, useful when you want to version-control an alternate routing config
  • env.yaml overrides: section — permanent multi-host routing shared across all developers

See Environments for full override and auth documentation.