Enterprise
Audit Logging
Maintain an immutable audit trail of every operation for compliance, debugging, and security monitoring.
What is Audit Logging?
An audit log is an append-only record of everything that happens in your system — who did what, when, and what the result was. Think of it like a security camera for your data operations.
Unlike regular application logs that you might delete or rotate, audit logs are immutable — once written, they can never be modified or deleted. This is a requirement for compliance frameworks like SOC 2, HIPAA, and GDPR.
Why You Need It
Compliance
If your application handles sensitive data (healthcare records, financial information, personal data), auditors will ask: "Can you show me who accessed what data and when?" Memcity's audit log gives you that answer automatically.
Debugging
When something goes wrong in production — "Why did the search return wrong results for this user?" — the audit log shows you exactly which pipeline steps ran, what the query was, how many results were returned, and how long it took.
Security Monitoring
If someone is trying to access documents they shouldn't see (ACL denials), or if there's an unusual spike in API usage, the audit log captures it. You can build alerts on top of audit log queries.
How It Works
Automatic Recording
Once enabled, every operation is logged automatically — you don't need to add any logging code. Memcity instruments the pipeline internally.
const memory = new Memory(components.memcity, {
tier: "team",
enterprise: {
auditLog: true, // That's it. Everything is now logged.
},
});What Gets Logged
Search Operations
Every getContext call is logged with:
{
"action": "search",
"timestamp": "2024-03-15T14:30:00.000Z",
"actor": "user:alice",
"orgId": "org_abc123",
"knowledgeBaseId": "kb_xyz",
"details": {
"query": "What is the refund policy?",
"queryType": "simple",
"resultsCount": 5,
"topScore": 0.94,
"pipelineSteps": ["cache_miss", "embed", "semantic_search", "bm25_search", "rrf_fusion", "dedup", "rerank", "format"],
"latencyMs": 342,
"cached": false
}
}Ingestion Operations
Every document ingestion is logged:
{
"action": "ingest",
"timestamp": "2024-03-15T14:25:00.000Z",
"actor": "system",
"orgId": "org_abc123",
"details": {
"documentId": "doc_xyz",
"source": "vacation-policy.md",
"knowledgeBaseId": "kb_xyz",
"chunksCreated": 12,
"entitiesExtracted": 8,
"processingTimeMs": 2340
}
}Deletion Operations
Document, knowledge base, and user deletions:
{
"action": "delete_document",
"timestamp": "2024-03-15T15:00:00.000Z",
"actor": "user:bob",
"orgId": "org_abc123",
"details": {
"documentId": "doc_xyz",
"cascadeResults": {
"chunksDeleted": 12,
"entitiesOrphaned": 3,
"edgesRemoved": 5,
"storageFreed": true
}
}
}ACL Changes
Every permission change is tracked:
{
"action": "set_acl",
"timestamp": "2024-03-15T14:45:00.000Z",
"actor": "user:admin",
"orgId": "org_abc123",
"details": {
"documentId": "doc_xyz",
"previousPrincipals": ["group:hr"],
"newPrincipals": ["group:hr", "group:engineering", "role:admin"]
}
}Access Denied Events
When ACLs block access, it's logged:
{
"action": "access_denied",
"timestamp": "2024-03-15T14:35:00.000Z",
"actor": "user:charlie",
"orgId": "org_abc123",
"details": {
"documentId": "doc_xyz",
"userPrincipals": ["user:charlie", "group:engineering"],
"requiredPrincipals": ["group:hr", "role:admin"],
"query": "salary information"
}
}Querying the Audit Log
Basic Retrieval
// Get recent audit log entries
const logs = await memory.getAuditLog(ctx, {
orgId,
limit: 50,
});
for (const entry of logs) {
console.log(`${entry.timestamp} [${entry.action}] by ${entry.actor}`);
}Filtering by Action Type
// Only search operations
const searchLogs = await memory.getAuditLog(ctx, {
orgId,
action: "search",
limit: 100,
});Filtering by Time Range
// Last 24 hours
const recentLogs = await memory.getAuditLog(ctx, {
orgId,
after: Date.now() - 24 * 60 * 60 * 1000,
limit: 200,
});Filtering by Actor
// Everything a specific user did
const userLogs = await memory.getAuditLog(ctx, {
orgId,
actor: "user:alice",
limit: 50,
});Integration with ACLs
When both enterprise.acl and enterprise.auditLog are enabled, the audit log becomes especially powerful:
- Access granted — Logged with which principals matched
- Access denied — Logged with which principals the user had vs. which were required
- ACL changes — Logged with before and after states
This gives you a complete picture of who accessed what data and who was blocked.
Retention and Storage
Audit logs are stored in Convex's database alongside your other data. They persist indefinitely — there is no automatic retention policy or rotation.
If you need to export audit logs to an external system (SIEM, data warehouse), you can query them programmatically and push to your preferred destination.
Storage impact: Each audit entry is typically 200-500 bytes. At 1,000 searches per day, that's ~500KB/day or ~15MB/month. Convex's storage is inexpensive, so this is a negligible cost.
Audit Log Entry Schema
| Field | Type | Description |
|---|---|---|
action | string | Operation type: search, ingest, delete_document, set_acl, access_denied, set_quota |
timestamp | string | ISO 8601 timestamp |
actor | string | Who performed the action: user:xxx, system, or api_key:xxx |
orgId | string | Organization context |
details | object | Action-specific data (query, results, timing, etc.) |
Availability
Audit Logging is available on the Team tier only ($179 one-time).