Scouttlo
All ideas/billing, metering, analytics/A hybrid metering SaaS platform combining fast aggregation with on-demand recompute, support for COUNT(DISTINCT) metrics, advanced lifecycle management, and secure handling of historical event backfill and soft deprecation.
GitHubB2BDevToolsbilling, metering, analytics

A hybrid metering SaaS platform combining fast aggregation with on-demand recompute, support for COUNT(DISTINCT) metrics, advanced lifecycle management, and secure handling of historical event backfill and soft deprecation.

Scouted 7 hours ago

7.3/ 10
Overall score

Turn this signal into an edge

We help you build it, validate it, and get there first.

From detected pain to an actionable plan: who pays, which MVP to launch first, how to validate it with real users, and what to measure before spending months.

Expanded analysis

See why this idea is worth it

Unlock the full write-up: what the opportunity really means, what problem exists today, how this idea attacks the pain, and the key concepts you need to know to build it.

We'll only use your email to send you the digest. Unsubscribe any time.

Score breakdown

Urgency8.0
Market size7.0
Feasibility8.0
Competition6.0
The pain

Event aggregation at ingestion time prevents retroactive recompute, counting unique users, managing lifecycle states, and easily correcting historical or fraudulent events.

Who'd pay

B2B SaaS companies requiring accurate billing, detailed usage analytics, and flexible metric management on PostgreSQL environments.

Signal that triggered it

"ORB solves this by storing raw events immutably and computing on-demand. We adopt the hybrid approach: keep UsageAggregate for the hot path, add a cold-path on-demand recompute layer."

Original post

[FEATURE] Phase 2 — Metering hybrid enhancements (recompute, COUNT(DISTINCT), lifecycle)

Published: 7 hours ago

Repository: granit-fx/granit-dotnet Author: jfmeyers ## Description **Problem.** `Granit.Metering` aggregates events at ingestion time via a hourly background job (`MeteringAggregationJob`) into pre-computed `UsageAggregate` rows. This works for hot-path reads (quota checks, dashboards) but rules out: - **Retroactive recompute** when a meter formula or a historical event changes - **`COUNT(DISTINCT)`** on a property in `Metadata` (e.g., bill per *unique active user*, not per *request*) - **Lifecycle**: a meter is binary `Activated` (bool) — no Draft state for testing, no Archived state for sunset - **Backfill**: events with `Timestamp` older than 7 days are rejected - **Soft event deprecation**: no way to neutralize a fraudulent or bogus event without DELETE ORB solves this by storing raw events immutably and computing on-demand. We adopt the **hybrid** approach: keep `UsageAggregate` for the hot path, add a cold-path on-demand recompute layer. **Solution.** Augment `Granit.Metering` along seven axes (see User Stories). Critical addition: PostgreSQL **advisory locking** on `(MeterDefinitionId, TenantId)` to co-exclude the recompute endpoint and the hourly job — without this, concurrent execution corrupts aggregates. **Alternatives considered.** - *Pure query-based metering (full ORB parity)*: rejected — would require ClickHouse / TimescaleDB; scope explosion. The hybrid covers ~95% of B2B SaaS use cases on PostgreSQL. - *Inline SQL ad-hoc metric definitions*: deferred (security design needed — see Spike story) ## User Stories - #1165 - Replace MeterDefinition.Activated with WorkflowLifecycleStatus - #1166 - Add CountDistinct aggregation type with DistinctProperty - #1167 - Add on-demand recompute endpoint with PostgreSQL advisory locking - #1168 - Add events backfill API for historical timestamps - #1169 - Add soft event deprecation with auto-recompute trigger - #1170 - Migrate GET /metering/meters to QueryEngine pagination + filters - #1171 - [SPIKE] SQL ad-hoc metric definitions — security & sandboxing design ## Expected deliverables - [ ] Lifecycle migration: `MeterDefinition.Activated` (bool) → `Status` (`WorkflowLifecycleStatus`) - [ ] `AggregationType.CountDistinct` + `MeterDefinition.DistinctProperty` (JSON path) - [ ] `POST /metering/meters/{id}/recompute` endpoint with PostgreSQL advisory lock - [ ] `POST /metering/events/backfill` endpoint with auto-recompute trigger - [ ] `MeterEvent.DeprecatedAt` + soft-deprecation endpoint - [ ] `GET /metering/meters` migrated to QueryEngine pagination + status/type filters - [ ] Spike: SQL ad-hoc metric definitions — security & sandboxing design ## Compliance - **GDPR**: Backfill events still subject to retention policy (no extended history smuggled in); `DeprecationReason` on event soft-delete may not contain PII - **ISO 27001**: Recompute and deprecate operations audited via `AuditedEntity` interceptor + dedicated metric counters - **Backward compatibility**: - `Activated` bool kept as computed property `bool Activated => Status == Published` for at least 1 release - `POST /metering/meters/{id}/deactivate` kept as deprecated alias for 1 release - `GET /metering/meters` response shape change (paged envelope) → release notes flagged ## Effort 2-3 weeks. **Minor breaking changes**: `AggregationType.CountDistinct` (additive OK), `deactivate` endpoint deprecated, `GET /meters` response paginated. ## Branch `feature/metering-orb-alignment` ## Dependencies Depends on Phase 1 (Granit.Catalog) being merged — `MeterDefinition.ItemId` already added there. Stories here can reference Catalog items in their own DTOs and validators. ## Parent Part of #1155 — Align Granit framework on ORB billing concepts (Phase 2). Cross-references existing module EPIC #833.

Your daily digest

Liked this one? Get 5 like it every morning.

SaaS opportunities scored by AI on urgency, market size, feasibility and competition. Curated from Reddit, HackerNews and more.

Free. No spam. Unsubscribe any time.