neo4j-contrib/neo4j-skills

neo4j-aura-provisioning-skill

Provisions and manages Neo4j Aura instances via CLI (aura-cli v1.7+) or REST API. Use when creating, pausing, resuming, resizing, or deleting AuraDB Free/Professional/Business Critical/VDC instances; downloading credentials; scripting CI/CD pipelines; polling async status; or using the Terraform neo4j/neo4j-aura provider. Covers auth setup (client credentials OAuth2), credential lifecycle (download once — never recoverable), instance type selection, region codes, and Python provisioning scripts…

Trending #6612 First seen Apr 28, 2026

Installation

$ npx skills add neo4j-contrib/neo4j-skills --skill neo4j-aura-provisioning-skill

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from neo4j-contrib/neo4j-skills · top by installs.

npx skills add neo4j-contrib/neo4j-skills

Browse all from neo4j-contrib/neo4j-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 108
License LICENSE
Default branch main
Open issues 2
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.4
Allowed toolsBash WebFetch

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 15,042 B
  • docs README.md 479 B
  • docs SUMMARY.md 772 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 498 installs

SKILL.md

When to Use

  • Creating an Aura instance (CLI, REST API, Python, Terraform)
  • Pausing, resuming, resizing, or deleting an instance
  • Downloading initial credentials from creation response
  • Polling instance status: creatingrunning
  • Setting up CI/CD provisioning or teardown pipelines
  • Choosing instance tier (Free vs Professional vs Business Critical vs VDC)

When NOT to Use

  • Cypher queries against running DBneo4j-cypher-skill
  • GDS algorithms on Auraneo4j-gds-skill (Pro with plugin) or neo4j-aura-graph-analytics-skill (serverless)
  • neo4j-admin / cypher-shellneo4j-cli-tools-skill
  • Application driver setup → use a language driver skill (python, javascript, java, go, dotnet)

Instance Tier Decision Table

Tier API type code Memory GDS Replicas Use when
AuraDB Free free-db 1 GB Dev/demo; ≤200k nodes/400k rels
AuraDB Professional professional-db 2–64 GB plugin available Production workloads
AuraDB Business Critical business-critical 4–384 GB plugin available HA, multi-AZ, SLA
AuraDB VDC enterprise-db custom Dedicated infra, compliance
AuraDS Professional professional-ds 2–64 GB ✅ built-in Data science / GDS
AuraDS Enterprise enterprise-ds custom Enterprise GDS

AuraDB Free limits: 200k nodes, 400k rels; auto-pauses after 72 h inactivity; deleted if paused >30 days; no resize.


Auth Setup

CLI (aura-cli v1.7+)

Install (binary, not pip):

# macOS
curl -L https://github.com/neo4j/aura-cli/releases/latest/download/aura-cli-darwin-amd64.tar.gz | tar xz
sudo mv aura-cli /usr/local/bin/
aura-cli -v          # verify

Add credentials (from console.neo4j.io → Account Settings → API Credentials):

aura-cli credential add \
  --name "my-creds" \
  --client-id "$AURA_CLIENT_ID" \
  --client-secret "$AURA_CLIENT_SECRET"
aura-cli credential use --name "my-creds"

Verify:

aura-cli instance list --output table

REST API — Get Bearer Token

Token endpoint: POST https://api.neo4j.io/oauth/token Token expires: 3600 s (1 h). On 403 → refresh token.

TOKEN=$(curl -s --request POST 'https://api.neo4j.io/oauth/token' \
  --user "${AURA_CLIENT_ID}:${AURA_CLIENT_SECRET}" \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  | jq -r '.access_token')
echo "Token: ${TOKEN:0:20}..."

Use in all subsequent calls: --header "Authorization: Bearer $TOKEN"


Step 1 — List Tenants (Projects)

CLI:

aura-cli tenants list --output table
# Copy TENANT_ID for create operations

REST:

curl -s https://api.neo4j.io/v1/tenants \
  -H "Authorization: Bearer $TOKEN" | jq '.data[] | {id, name}'

Step 2 — Create Instance

CRITICAL: Capture output immediately. Initial password shown ONCE — never retrievable again. If lost: delete and recreate. Store aura-creds.json before doing anything else.

CLI

aura-cli instance create \
  --name "my-instance" \
  --cloud-provider gcp \
  --region europe-west1 \
  --type professional-db \
  --tenant-id "$TENANT_ID" \
  --output json | tee aura-creds.json

# Extract for .env
INSTANCE_ID=$(jq -r '.id' aura-creds.json)
PASSWORD=$(jq -r '.password' aura-creds.json)

REST API (full create)

RESPONSE=$(curl -s -X POST https://api.neo4j.io/v1/instances \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name":           "my-instance",
    "cloud_provider": "gcp",
    "region":         "europe-west1",
    "type":           "professional-db",
    "tenant_id":      "'"$TENANT_ID"'",
    "memory":         "4GB",
    "version":        "5"
  }')
echo "$RESPONSE" | tee aura-creds.json
INSTANCE_ID=$(echo "$RESPONSE" | jq -r '.data.id')
PASSWORD=$(echo "$RESPONSE"   | jq -r '.data.password')

Instance create request body fields:

Field Required Values
name any string
cloud_provider gcp aws azure
region see region table
type see tier table
tenant_id from tenant list
memory 1GB 2GB 4GB 8GB384GB
version 5 (default)

Step 3 — Poll Until RUNNING (CRITICAL — All Ops Are Async)

ALL lifecycle operations (create, pause, resume, resize) are async. Do NOT attempt connection or next operation until status = running (or paused for pause op).

poll_status() {
  local INSTANCE_ID=$1 TARGET=$2 MAX_WAIT=${3:-600}
  local ELAPSED=0 STATUS
  echo "Polling for status=$TARGET (max ${MAX_WAIT}s)..."
  while [ $ELAPSED -lt $MAX_WAIT ]; do
    STATUS=$(aura-cli instance get --instance-id "$INSTANCE_ID" --output json \
             | jq -r '.status' 2>/dev/null)
    echo "  [${ELAPSED}s] status=$STATUS"
    [ "$STATUS" = "$TARGET" ] && echo "Ready." && return 0
    [ "$STATUS" = "destroying" ] && echo "ERROR: instance is being destroyed" && return 1
    sleep 10; ELAPSED=$((ELAPSED + 10))
  done
  echo "TIMEOUT after ${MAX_WAIT}s — last status: $STATUS" && return 1
}

poll_status "$INSTANCE_ID" "running" 600

REST equivalent:

while true; do
  STATUS=$(curl -s "https://api.neo4j.io/v1/instances/$INSTANCE_ID" \
    -H "Authorization: Bearer $TOKEN" | jq -r '.data.status')
  [ "$STATUS" = "running" ] && break
  sleep 10
done

Status lifecycle:

creating → running → pausing → paused → resuming → running
                  ↘ destroying → (gone)

Step 4 — Write .env and Verify

CONNECTION_URI="neo4j+s://${INSTANCE_ID}.databases.neo4j.io"

cat > .env <<EOF
NEO4J_URI=${CONNECTION_URI}
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=${PASSWORD}
NEO4J_DATABASE=neo4j
AURA_INSTANCE_ID=${INSTANCE_ID}
EOF

# Ensure .env never committed
grep -q '^\.env$' .gitignore 2>/dev/null || echo '.env' >> .gitignore

# Verify connectivity
cypher-shell -a "$CONNECTION_URI" -u neo4j -p "$PASSWORD" "RETURN 'connected' AS status"

Step 5 — Lifecycle Operations

All operations require instance in the correct state. Wrong-state ops return 4xx error.

Pause

Required state: running

aura-cli instance pause --instance-id "$INSTANCE_ID"
poll_status "$INSTANCE_ID" "paused" 600

Resume

Required state: paused

aura-cli instance resume --instance-id "$INSTANCE_ID"
poll_status "$INSTANCE_ID" "running" 900   # resume can take longer

Resize (Professional+ only — NOT Free)

Required state: running; instance remains available during resize.

# REST only — CLI resize not available in v1.7
curl -s -X PATCH "https://api.neo4j.io/v1/instances/$INSTANCE_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"memory": "8GB"}'
poll_status "$INSTANCE_ID" "running" 600
# Cannot reduce below current usage level

Delete

IRREVERSIBLE. Export snapshots first if data needed.

aura-cli instance delete --instance-id "$INSTANCE_ID"
# No poll needed — immediate

REST:

curl -s -X DELETE "https://api.neo4j.io/v1/instances/$INSTANCE_ID" \
  -H "Authorization: Bearer $TOKEN"

Python CI/CD Provisioning Script

import os, time, requests

CLIENT_ID     = os.environ["AURA_CLIENT_ID"]
CLIENT_SECRET = os.environ["AURA_CLIENT_SECRET"]
BASE          = "https://api.neo4j.io/v1"

def get_token() -> str:
    r = requests.post(
        "https://api.neo4j.io/oauth/token",
        auth=(CLIENT_ID, CLIENT_SECRET),
        data={"grant_type": "client_credentials"},
    )
    r.raise_for_status()
    return r.json()["access_token"]

def auth_headers(token: str) -> dict:
    return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}

def create_instance(token: str, tenant_id: str, **kwargs) -> dict:
    payload = {"tenant_id": tenant_id, "version": "5", **kwargs}
    r = requests.post(f"{BASE}/instances", headers=auth_headers(token), json=payload)
    r.raise_for_status()
    return r.json()["data"]   # contains id, password, connection_url

def poll_status(token: str, instance_id: str, target: str, timeout: int = 600) -> None:
    deadline = time.time() + timeout
    while time.time() < deadline:
        r = requests.get(f"{BASE}/instances/{instance_id}", headers=auth_headers(token))
        r.raise_for_status()
        status = r.json()["data"]["status"]
        print(f"  status={status}")
        if status == target:
            return
        if status == "destroying":
            raise RuntimeError("Instance destroyed unexpectedly")
        time.sleep(10)
    raise TimeoutError(f"Instance {instance_id} did not reach '{target}' in {timeout}s")

# --- usage ---
token    = get_token()
instance = create_instance(
    token,
    tenant_id = os.environ["AURA_TENANT_ID"],
    name           = "ci-test-instance",
    cloud_provider = "aws",
    region         = "us-east-1",
    type           = "professional-db",
    memory         = "2GB",
)
# SAVE CREDENTIALS IMMEDIATELY — password never retrievable again
print(f"ID:       {instance['id']}")
print(f"URI:      neo4j+s://{instance['id']}.databases.neo4j.io")
print(f"Password: {instance['password']}")   # log to secure vault NOW

poll_status(token, instance["id"], "running", timeout=600)
print("Instance ready.")

Region Codes

AWS

Region code Location
us-east-1 N. Virginia
us-east-2 Ohio
us-west-2 Oregon
eu-west-1 Ireland
eu-west-3 Paris
eu-central-1 Frankfurt
ap-southeast-1 Singapore
ap-southeast-2 Sydney
ap-south-1 Mumbai
sa-east-1 São Paulo

GCP

Region code Location
europe-west1 Belgium
europe-west3 Frankfurt
europe-west4 Netherlands
us-central1 Iowa
us-east1 S. Carolina
us-east4 N. Virginia
asia-east1 Taiwan
asia-northeast1 Tokyo
asia-southeast1 Singapore
australia-southeast1 Sydney

Azure

Region code Location
eastus E. US
eastus2 E. US 2
westeurope Netherlands
northeurope Ireland
uksouth London
southeastasia Singapore
brazilsouth Brazil
koreacentral Korea

Enterprise tiers (Business Critical, VDC) add 20+ additional regions per provider. Check console for full list. Free tier: GCP only; limited subset of regions.


Terraform Provider

terraform {
  required_providers {
    aura = {
      source  = "neo4j/neo4j-aura"
    }
  }
}

provider "aura" {
  client_id     = var.aura_client_id       # or AURA_CLIENT_ID env var
  client_secret = var.aura_client_secret   # or AURA_CLIENT_SECRET env var
}

resource "aura_instance" "db" {
  name           = "prod-db"
  type           = "professional-db"
  cloud_provider = "gcp"
  region         = "europe-west1"
  memory         = "4GB"
  tenant_id      = var.aura_tenant_id
}

output "neo4j_uri" {
  value     = "neo4j+s://${aura_instance.db.id}.databases.neo4j.io"
  sensitive = false
}
output "neo4j_password" {
  value     = aura_instance.db.password
  sensitive = true
}

After terraform apply: poll status before marking infra ready — Terraform resource creation returns when API call completes, not when DB is running.


Common Errors

Error Cause Fix
403 Forbidden after working Token expired (1 h TTL) Re-run get_token()
409 Conflict on create Name already exists in tenant Change name or delete existing
422 on pause Instance not running Check status; wait for ongoing op to finish
422 on resume Instance not paused Check status
422 on resize Below current usage Reduce data first; can't shrink below usage
Region not found Tier doesn't support that region Use Free tier on GCP only; Pro/BC on all 3 clouds
Credentials lost after create Password only returned at create time Delete + recreate — no reset exists
429 Too Many Requests Rate limit hit (25 req/min Free, 125 req/min Pro+) Add time.sleep(2) between polling calls
instance list returns empty Wrong credential active aura-cli credential use --name <name>

API Rate Limits

Tier Requests/minute
Free / Pro Trial (no billing) 25
Pro with billing, BC, VDC 125

Poll interval: ≥10 s to stay within limits on Free; 5 s safe on Pro+. On Retry-After header in 5xx response: wait that many seconds before retry.


Security Rules

  • Write initial credentials to .env; verify .env in .gitignore before proceeding
  • Never print PASSWORD in CI logs — write to secrets vault (AWS Secrets Manager, GitHub secret, Vault)
  • Use from_env() / os.environ — never hardcode credentials
  • If .env absent: python-dotenv load_dotenv() auto-loads; do NOT prompt user unless loading fails

WebFetch — Current Docs

Need URL
REST API spec (OpenAPI) https://neo4j.com/docs/aura/platform/api/specification/
CLI reference https://neo4j.com/docs/aura/aura-cli/
Region list https://neo4j.com/docs/aura/managing-instances/regions/
Auth details https://neo4j.com/docs/aura/api/authentication/
Instance actions https://neo4j.com/docs/aura/managing-instances/instance-actions/

Checklist

  • .env created with URI/user/password; .env in .gitignore
  • Initial credentials saved to secure storage immediately after create
  • poll_status called after create — do NOT connect before status = running
  • poll_status called after pause/resume
  • Correct tier selected (Free for dev, Pro+ for production, BC for HA)
  • Region confirmed available for chosen tier and cloud provider
  • Tenant ID provided for all create/list operations (required in multi-tenant orgs)
  • Token refreshed if > 1 h old (or 403 received)
  • Delete confirmed by user — data loss is permanent, no recovery