A standalone FastAPI microservice that pre-validates names against cached metadata and provides fuzzy suggestions. Works with any hierarchical namespace (database objects, API paths, config keys, etc.). Supports multiple environments (prod, stage, qa, dev).
This service acts as a gatekeeper before actual API calls:
- Always validates against in-memory cached metadata
- Never hits the actual source for validation
- Returns validation results that consuming applications use to decide whether to proceed
- Supports multiple environments with separate metadata caches
User Input → NameGuard → valid/suggestions/not_found → (if valid) → Actual API
pip install -r requirements.txtCreate pickle files for each environment in the data/ directory:
data/metadata_prod.pkldata/metadata_stage.pkldata/metadata_qa.pkldata/metadata_dev.pkl
Expected structure for each pickle file:
{
"schemas": {
"public": {
"tables": {
"student": ["id", "name", "email"],
"course": ["id", "title", "credits"]
}
},
"hr": {
"tables": {
"employee": ["emp_id", "first_name", "salary"]
}
}
},
"exported_at": "2026-01-21T10:00:00Z"
}Or use the sample script to create test data:
python scripts/create_sample_pickle.pyuvicorn app.main:app --host 0.0.0.0 --port 8000Visit http://localhost:8000/docs for interactive Swagger documentation.
Validates a name against cached metadata. Call this BEFORE hitting your actual API.
Request:
{
"environment": "prod",
"scope": "table",
"search_term": "student",
"context": {
"schema_name": "public"
}
}Response (valid):
{
"status": "valid",
"match": "student",
"suggestions": null
}Response (suggestions):
{
"status": "suggestions",
"match": null,
"suggestions": [
{"name": "student", "score": 92},
{"name": "students", "score": 85}
]
}Response (not_found):
{
"status": "not_found",
"match": null,
"suggestions": []
}Real-time suggestions for autocomplete/typeahead. Matches on actual object name, returns qualified path.
Request:
GET /api/v1/suggest?environment=dev&scope=table&q=stu&threshold=50&limit=5
Response:
["public.student", "public.instructor"]Same as /suggest but includes similarity scores.
Response:
[
{"name": "public.student", "score": 90},
{"name": "public.instructor", "score": 60}
]List all available environments.
Health check with cache statistics.
Environment variables (prefix: NAMEGUARD_):
| Variable | Default | Description |
|---|---|---|
NAMEGUARD_PICKLE_BASE_DIR |
data |
Directory containing pickle files |
NAMEGUARD_FUZZY_THRESHOLD |
50 |
Minimum similarity score (0-100) |
NAMEGUARD_MAX_SUGGESTIONS |
5 |
Maximum suggestions to return |
NAMEGUARD_API_PREFIX |
/api/v1 |
API route prefix |
NAMEGUARD_AVAILABLE_ENVIRONMENTS |
["prod", "stage", "qa", "dev"] |
Environments to load |
nameguard/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI app with lifespan
│ ├── config.py # pydantic-settings configuration
│ ├── models/
│ │ ├── __init__.py
│ │ └── schemas.py # Request/Response Pydantic models
│ ├── services/
│ │ ├── __init__.py
│ │ ├── metadata_cache.py # Multi-environment cache manager
│ │ ├── validator.py # Scope-aware validation logic
│ │ └── fuzzy_matcher.py # RapidFuzz wrapper
│ └── routers/
│ ├── __init__.py
│ ├── validate.py # /validate endpoint
│ └── suggest.py # /suggest endpoint
├── standalone/ # Standalone library (no FastAPI)
│ ├── __init__.py
│ ├── metadata_cache.py
│ ├── validator.py
│ ├── fuzzy_matcher.py
│ └── cli.py # Command-line interface
├── data/
│ ├── metadata_prod.pkl
│ ├── metadata_stage.pkl
│ ├── metadata_qa.pkl
│ └── metadata_dev.pkl
├── scripts/
│ ├── create_sample_pickle.py
│ └── csv_to_pickle.py
├── requirements.txt
└── README.md
- Multi-Environment Support: Separate caches for prod/stage/qa/dev
- Fuzzy Matching: RapidFuzz for high-performance string matching
- Qualified Names: Returns
schema.table.columnformat - O(1) Exact Match: Uses sets for instant lookups
- Configurable Threshold: Adjustable similarity threshold per request
- Standalone Library: Use without FastAPI via
standalone/module - CLI Tool: Command-line validation via
standalone/cli.py
For embedding in other projects without the API:
from standalone import MetadataCache, Validator
cache = MetadataCache()
cache.load_from_pickle("data/metadata_dev.pkl")
validator = Validator(cache)
result = validator.validate_table("student", schema="public")
if result.is_valid():
print(f"Found: {result.match}")
elif result.has_suggestions():
for s in result.suggestions:
print(f"Did you mean: {s.name} ({s.score}%)")python standalone/cli.py table student public
python standalone/cli.py table studnt public # Shows suggestions for typo