Vizoalica v0.1.0 Architecture Discussion
Status: Historical design discussion for v0.1.0; not current operating guidance. For how Vizoalica works and is run today, see the README and operations guides.
Date: 2026-08-15
Related spec: specs/001-event-collection-foundation/spec.md
Goal
Define a minimal but expandable first release: a safe embeddable web snippet and a high-volume ingestion backend for privacy-aware product analytics.
Design direction
- Accept small HTTPS event batches with strict payload, event-count, and validation limits.
- Carry consent state explicitly without attempting to provide the website's consent interface.
- Load the browser SDK asynchronously and require privacy review for any added metadata.
- Use short-lived server-issued tokens for production ingestion; never treat a browser-visible key as secret.
- Apply request and quota limits before expensive processing to bound abuse and infrastructure cost.
Non-negotiable constraints
- Website safety: analytics must never break the host website.
- Privacy by default: collect less, redact aggressively, require explicit opt-in for richer metadata.
- Abuse-bounded ingestion: reject bad traffic before expensive processing.
- Tenant/project isolation: one abusive project cannot degrade others.
- Open-source/low-cost economics: a simple Cloudflare-native default deployment and predictable storage growth.
- Expansion-ready data: event schemas must support future dashboards, exports, and AI insights.
Proposed v0.1.0 shape
Browser snippet responsibilities
- Load asynchronously and avoid blocking page rendering.
- Capture page views and explicitly invoked custom events.
- Maintain a small in-memory queue with bounded size.
- Use browser-native delivery that is safe during navigation when available.
- Drop events when offline, over limit, or repeatedly failing rather than impacting the page.
- Apply client-side privacy filters before sending, while relying on backend validation as authoritative.
- Include project/source identifier, event name, timestamp, consent state, anonymous session/visitor context, and validated custom properties.
Ingestion responsibilities
- Receive browser event batches.
- Validate origin, project/source status, schema, event age, event count, payload size, and property limits.
- Apply rate limits and quotas before persistence.
- Persist accepted events or stage them durably for later processing.
- Record aggregate operational metrics: accepted, rejected, throttled, bytes received, and rejection reasons.
- Avoid logging raw event payloads by default.
Key tradeoffs
Authenticity: public snippet key vs. server-attested events
- Public project key only: easiest installation, but anyone can copy it and send fake data. Use only as a routing identifier plus origin/quota checks.
- Shared secret in browser: not acceptable; browser secrets are extractable and create false confidence.
- Server-issued short-lived token: stronger for authenticated apps because the customer backend can mint scoped tokens. More work for customers, but best expansion path.
- Signed server-side events: strongest for events emitted from the customer's backend, but does not cover purely browser-observed interactions.
Recommended v0.1.0 position: support public project/source identifiers for minimal setup, document their limits, and design the schema/configuration so short-lived server-attested tokens can be added without breaking changes.
Privacy: useful defaults vs. accidental sensitive data
- Rich metadata improves segmentation but increases risk.
- Automatic DOM/form capture is powerful but dangerous for v0.1.0.
- URL capture is useful, but query strings often contain tokens and personal data.
Recommended v0.1.0 position: page URL origin/path allowed by default, query values redacted by default, no DOM text or form values, custom properties allowed only within strict size/type/name limits.
High volume: direct writes vs. buffered ingestion
- Direct event writes are simpler but can make storage the bottleneck and raise write costs under abuse.
- Buffered ingestion adds operational complexity but improves burst handling and isolation.
Recommended v0.1.0 discussion point: choose the simplest durable path that can reject early and batch writes. If the first implementation uses direct writes, keep an internal ingestion boundary so a queue can be introduced later.
Consent: built-in banner vs. consent signal support
- Built-in consent UI increases product scope and legal surface area.
- Consent signal support lets customers integrate their existing consent management.
Recommended v0.1.0 position: support explicit consent state in configuration/events, but do not build a consent banner in the first release.
AI-ready: event quality now vs. AI features now
- AI insights need clean schemas, stable semantics, and access controls more than they need an LLM in v0.1.0.
- Adding AI features before governance risks privacy/security mistakes.
Recommended v0.1.0 position: make data structured, documented, exportable, and traceable. Defer actual AI features.
Open questions for discussion
- Primary first user: Is v0.1.0 for technical website owners only, or should it be approachable by non-expert website owners?
- Initial event set: Should v0.1.0 include only page views and custom events, or also clicks/navigation/engagement time?
- Identity level: Should anonymous session analytics be the default only, with authenticated visitor/account metadata deferred?
- Storage horizon: What default retention target keeps costs low while still useful: 30, 90, or 180 days?
- Authenticity option: Should server-issued short-lived tokens be required for v0.1.0, or introduced as an optional hardening path after public-key ingestion works?
- Target deployment: Decided — v0.1.0 will be Cloudflare-native. Other deployment profiles are deferred.
Suggested planning stance
For v0.1.0, optimize for a very small, trustworthy ingestion foundation:
- page view + custom event collection;
- no session replay, heatmaps, guides, or dashboards beyond minimal verification;
- strict event schema and privacy filters;
- public project/source identifier with honest limitations;
- origin allowlist, quotas, payload limits, and project isolation;
- documented extension path for stronger authenticity, richer identity, dashboards, exports, and AI insights.
Planning update: agreed standards direction
After discussion, v0.1.0 planning assumes:
- Production ingestion requires short-lived server-issued ingest tokens from day one.
- Browser-visible project/source identifiers are public routing identifiers, not secrets.
- Unsigned public-ID ingestion may exist only as explicitly marked demo/development mode.
- Events use CloudEvents JSON batch format as the transport/envelope standard.
- Event-specific payloads are validated with versioned JSON Schemas.
- Token claims use standard JWT/JOSE conventions.
- Optional correlation should be compatible with W3C Trace Context.
- Consent state is part of the event contract; IAB TCF strings may be carried when a site already uses that ecosystem.
- v0.1.0 will use Cloudflare Workers for ingestion, D1 for configuration/metadata, and R2 for raw-event batches. Other deployment profiles are deferred, while storage interfaces and event contracts remain portable.