Skip to main content

a6-persona-developer

Who This Is For

You are an API developer responsible for:

  • Designing and configuring API routes on APISIX
  • Choosing and configuring plugins for auth, rate limiting, transformation
  • Testing APIs locally against a development APISIX instance
  • Writing declarative configs for CI/CD pipelines
  • Debugging request flow through the gateway

Getting Started

1. Install and configure

# Install a6
go install github.com/api7/a6/cmd/a6@latest

# Connect to your dev APISIX instance
a6 context create dev --server http://localhost:9180 --api-key edd1c9f034335f136f87ad84b625c8f1

# Verify connection
a6 health

2. Explore available plugins

# List all available plugins
a6 plugin list

# Get the schema for a specific plugin
a6 plugin get key-auth --output json
a6 plugin get limit-count --output json

Building Your First API

Step 1: Create an upstream (your backend)

a6 upstream create -f - <<'EOF'
{
"id": "my-api-backend",
"type": "roundrobin",
"nodes": {
"localhost:3000": 1
}
}
EOF

Step 2: Create a route

a6 route create -f - <<'EOF'
{
"id": "my-api",
"uri": "/api/*",
"methods": ["GET", "POST", "PUT", "DELETE"],
"upstream_id": "my-api-backend"
}
EOF

Step 3: Test it

curl http://localhost:9080/api/hello

Step 4: Add authentication

# Create a consumer with key-auth
a6 consumer create -f - <<'EOF'
{
"username": "dev-user",
"plugins": {
"key-auth": { "key": "my-dev-key" }
}
}
EOF

# Enable key-auth on the route
a6 route update my-api -f - <<'EOF'
{
"plugins": {
"key-auth": {}
}
}
EOF

# Test with the key
curl -H "apikey: my-dev-key" http://localhost:9080/api/hello

Plugin Selection Guide

Use this decision tree to choose the right plugins for your API.

Authentication — "Who is calling?"

NeedPluginKey Feature
Simple API keykey-authHeader/query param key lookup
JWT tokensjwt-authRS256/HS256, token in header/query/cookie
Username/passwordbasic-authHTTP Basic authentication
HMAC signatureshmac-authRequest body signing, replay prevention
OAuth2/OIDCopenid-connectAuth0, Okta, Keycloak integration

Rate Limiting — "How much can they call?"

NeedPluginKey Feature
Fixed window counterlimit-countN requests per time window, Redis cluster support
Leaky bucketlimit-reqSmooth rate limiting, burst allowance

Transformation — "Change request/response"

NeedPluginKey Feature
Rewrite URI/headersproxy-rewriteStrip prefixes, add headers, change host
Modify responseresponse-rewriteChange status code, body, headers
A/B testing, canarytraffic-splitWeighted routing, conditional matching
URL redirectredirectHTTP 301/302/307 redirects

Security — "Block bad traffic"

NeedPluginKey Feature
IP whitelist/blacklistip-restrictionCIDR support, allow/deny lists
CORS headerscorsCross-origin resource sharing
Access controlconsumer-restrictionRestrict by consumer, group, or route

Observability — "What's happening?"

NeedPluginKey Feature
MetricsprometheusLatency, status codes, bandwidth
Distributed tracingzipkin or skywalkingRequest trace correlation
Access logshttp-logger or kafka-loggerStructured log export

Common Patterns

API with auth + rate limiting

a6 route create -f - <<'EOF'
{
"uri": "/api/*",
"upstream_id": "my-api-backend",
"plugins": {
"key-auth": {},
"limit-count": {
"count": 1000,
"time_window": 3600,
"key_type": "var",
"key": "consumer_name",
"rejected_code": 429
}
}
}
EOF

Strip version prefix

a6 route create -f - <<'EOF'
{
"uri": "/v1/*",
"upstream_id": "my-api-backend",
"plugins": {
"proxy-rewrite": {
"regex_uri": ["^/v1/(.*)", "/$1"]
}
}
}
EOF

Add CORS for frontend apps

a6 route update my-api -f - <<'EOF'
{
"plugins": {
"cors": {
"allow_origins": "http://localhost:3001",
"allow_methods": "GET,POST,PUT,DELETE,OPTIONS",
"allow_headers": "Authorization,Content-Type",
"allow_credential": true,
"max_age": 3600
}
}
}
EOF

Use a Service for shared config

When multiple routes share the same upstream and plugins, use a Service:

# Create service with shared config
a6 service create -f - <<'EOF'
{
"id": "my-api-service",
"upstream_id": "my-api-backend",
"plugins": {
"key-auth": {},
"cors": { "allow_origins": "*" }
}
}
EOF

# Routes inherit service config
a6 route create -f - <<'EOF'
{ "uri": "/users/*", "service_id": "my-api-service" }
EOF

a6 route create -f - <<'EOF'
{ "uri": "/orders/*", "service_id": "my-api-service" }
EOF

Local Development Setup

Start APISIX locally with Docker

# If using the a6 repo's docker-compose
make docker-up

# Or manually
docker run -d --name etcd \
-p 2379:2379 \
-e ALLOW_NONE_AUTHENTICATION=yes \
bitnami/etcd:3.5

docker run -d --name apisix \
-p 9080:9080 -p 9180:9180 \
-v $(pwd)/apisix-config.yaml:/usr/local/apisix/conf/config.yaml \
apache/apisix:3.11.0-debian

Seed development data

# Create your dev config file
cat > dev-config.yaml <<'EOF'
upstreams:
- id: local-backend
type: roundrobin
nodes:
"host.docker.internal:3000": 1

consumers:
- username: dev
plugins:
key-auth:
key: dev-key

routes:
- id: api
uri: "/api/*"
upstream_id: local-backend
plugins:
key-auth: {}
EOF

# Apply it
a6 config sync -f dev-config.yaml

Debugging

Trace a request

# See how APISIX routes a specific request
a6 debug trace --uri /api/users --method GET --header "apikey: dev-key"

Stream logs

# Watch APISIX error logs in real-time
a6 debug logs --follow

# Filter by log level
a6 debug logs --follow --level error

Inspect a route's full config

# See the merged config (route + service + plugins)
a6 route get my-api --output json | jq .

CI/CD Integration

Validate in CI

# .github/workflows/apisix.yml
- name: Validate APISIX config
run: a6 config validate -f apisix-config.yaml

Deploy with config sync

- name: Deploy to staging
run: |
a6 context create staging --server ${{ secrets.STAGING_URL }} --api-key ${{ secrets.STAGING_KEY }}
a6 context use staging
a6 config diff -f apisix-config.yaml
a6 config sync -f apisix-config.yaml

Export for other tools

# Export to Kubernetes-friendly format
a6 export --format kubernetes > k8s-apisix.yaml

# Export to standalone YAML
a6 export --format standalone > apisix-standalone.yaml

Decision Framework

SituationAction
New API endpointCreate upstream → create route → add plugins → test
Add auth to existing APICreate consumer → update route with auth plugin → test
Multiple routes, same configCreate a Service → reference via service_id
Need rate limitingChoose limit-count (fixed) or limit-req (smooth) → add to route
Backend URL changeda6 upstream update <id> with new nodes
Debug 502 errorsa6 debug tracea6 upstream health → check backend
Prepare for productiona6 config dump → commit to git → a6 config validate in CI
Test a new plugina6 plugin get <name> for schema → add to a test route → verify

Best Practices

  1. Use declarative configs — store apisix-config.yaml in your repo, use a6 config sync for deployments instead of imperative commands
  2. One service per API — group related routes under a Service for shared config
  3. Auth on every route — never expose unauthenticated routes in production
  4. Rate limit by consumer — use key_type: "var" with key: "consumer_name" for per-user limits
  5. Test locally first — always test against a dev APISIX instance before deploying
  6. Inspect plugin schemas — run a6 plugin get <name> to see required/optional fields before configuring
  7. Use --output json — pipe JSON output to jq for scripting and automation
  8. Keep routes focused — one route per endpoint pattern; avoid overly broad URI matchers like /* in production

This page is generated from a6-persona-developer/SKILL.md in the api7/a6 repository. Browse all skills on the AI Agent Skills page.