Monday 08:53. Product shipped PostHog across the checkout funnel — feature flags for pricing_hero_v2, session replay for drop-off analysis, event capture wired to the product dashboard. Growth loves the single OSS suite. Then authorization alarms fire: processor timeouts climb, a card-testing ring hits BIN 424242, and the payments fleet needs fraud/thresholds/block_score at 71, resilience/payments/failure_rate_threshold at 24, and runtime/tomcat/max_threads raised across fourteen Spring Boot pods serving 15k auth evaluations per second.
The frontend lead suggests:
"PostHog has feature flags and multivariate config — add
block_scoreas a flag payload. One SDK, one analytics plane."
The authorization tech lead refuses:
"PostHog belongs on product surfaces where we want capture, replay, and cohort flags. Our auth filter runs before any product context exists — I will not put an analytics SDK with network calls and event buffering on the money path."
PostHog is a powerful all-in-one product analytics platform — feature flags, session replay, funnels, cohorts, and open-source self-hosting for product teams who want one vendor. Kiponos.io is a live operational config hub — typed nested trees, WebSocket deltas, and local reads in Java Spring Boot 3 and Python. Run PostHog for what users see and how product learns; Kiponos for how payment and fraud services behave under attack.
The problem — analytics feature flags on the authorization hot path
Correct PostHog usage for product surfaces:
// Correct — product BFF with analytics context
PostHog posthog = new PostHog.Builder(apiKey).build();
boolean showHeroV2 = posthog.isFeatureEnabled(
"pricing_hero_v2",
customerId,
Map.of("plan", planTier, "country", countryCode)
);
posthog.capture(customerId, "pricing_page_viewed", Map.of(
"variant", showHeroV2 ? "v2" : "control"
));
The anti-pattern appears when fraud and resilience keys land in PostHog flags:
// Anti-pattern — analytics SDK on saturated authorization filter
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class FraudAuthFilter implements Filter {
private final PostHog posthog;
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// Runs at 15k TPS — before product session exists
int blockScore = posthog.getFeatureFlagPayload(
"fraud_block_score",
"system-auth",
Integer.class,
85
);
// ...
}
}
Pain points:
- Analytics SDK on auth path — event buffering, identify calls, and flag polling add latency and failure modes where none belong
- Flags assume product identity — fraud thresholds are global system state, not a cohort multivariate payload
- Session replay and funnels are irrelevant — circuit breakers do not need replay to decide when to open
-
No nested ops tree —
resilience/payments/partner_adyen/timeout_msbecomes flat flag key sprawl - Python fraud scoring workers — no shared ops tree with Java authorization without duplicating PostHog flag definitions
- Self-hosted PostHog footprint — ClickHouse + Kafka + workers justified for product analytics; incident floats should not inflate the flag catalog
PostHog is excellent for product analytics with integrated feature flags. It is the wrong dependency on payment authorization and fraud hot paths.
What teams believe vs production reality
| Belief | Production reality |
|---|---|
| "One PostHog SDK simplifies the stack" | Product analytics and auth-path floats have different latency and privacy models |
| "Feature flag payloads replace ops config" | Built for cohort targeting, not nested platform trees |
| "OSS PostHog is free so use it everywhere" | ClickHouse + pipeline ops are real cost — scope to product |
| "Multivariate flags handle all runtime values" |
block_score = 71 is not a checkout hero variant |
| "We will keep YAML for auth and PostHog for web" | Now two config planes with no shared fraud tree across Java and Python |
The Aha
PostHog decides which users see which product experiences and records how they behave. Kiponos holds operational knobs — fraud scores, circuit thresholds, pool sizes — with local reads on paths that must never carry analytics SDKs. Keep pricing_hero_v2 in PostHog with session replay and funnel metrics. Move block_score, failure_rate_threshold, and max_threads to Kiponos.
What Kiponos.io is alongside PostHog product analytics
Kiponos is a real-time configuration hub. SDKs connect via WebSocket, load profile ['fintech']['auth']['prod']['live'], and mirror the tree in memory. Edit in dashboard → delta → next getInt() in any pod — no restart, no flag redeploy, no analytics identify round-trip.
PostHog remains your product analytics and experimentation plane for surfaces where capture and replay add value. Kiponos becomes your ops config plane for payment, fraud, and resilience values that change during incidents — same hub for Java authorization APIs and Python scoring workers, zero analytics overhead on the hot path.
Architecture — PostHog product plane vs Kiponos ops hub
PostHog stays on product-facing paths with analytics context. Kiponos serves system-bound values on paths that must stay analytics-free.
Config tree — ops structure PostHog flags were not designed to hold
fraud/
thresholds/
block_score: 71
review_score: 58
velocity_per_hour: 28
bin_attack_multiplier: 1.35
resilience/
payments/
failure_rate_threshold: 24
wait_duration_open_ms: 32000
permitted_calls_half_open: 6
partner_adyen/
timeout_ms: 2800
slow_call_rate_threshold: 0.45
runtime/
tomcat/
max_threads: 260
accept_count: 220
hikari/
maximum_pool_size: 48
minimum_idle: 16
connection_timeout_ms: 4200
ml/
bin_velocity/
batch_size: 256
worker_concurrency: 10
model_version: v4.1.0
posthog_bridge/
# Document flags that stay on PostHog
pricing_hero_v2: posthog_owned
onboarding_checklist_v3: posthog_owned
Java integration — fraud and circuits without analytics SDK
@Configuration
public class KiponosConfig {
@Bean
public Kiponos kiponos(
@Value("${kiponos.team-id}") String teamId,
@Value("${kiponos.access-key}") String accessKey,
@Value("${kiponos.profile-path}") String profilePath) {
return Kiponos.builder()
.teamId(teamId)
.accessKey(accessKey)
.profilePath(profilePath)
.build();
}
}
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class FraudAuthFilter implements Filter {
private final Kiponos kiponos;
public FraudAuthFilter(Kiponos kiponos) {
this.kiponos = kiponos;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) req;
int riskScore = extractRiskScore(httpReq);
int hourlyVelocity = extractVelocity(httpReq);
var fraud = kiponos.path("fraud", "thresholds");
int blockScore = fraud.getInt("block_score");
int velocityLimit = fraud.getInt("velocity_per_hour");
if (hourlyVelocity > velocityLimit || riskScore >= blockScore) {
((HttpServletResponse) res).sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
chain.doFilter(req, res);
}
}
Bind Tomcat threads when ops raises capacity during a flash event:
@PostConstruct
void bindThreadKnobs() {
kiponos.afterValueChanged(change -> {
if (change.getPath().startsWith("runtime/tomcat/max_threads")) {
tomcatConnectorCustomizer.setMaxThreads(change.getNewValueAsInt());
}
});
}
Product flag — keep PostHog where analytics and replay belong:
public PricingHero resolveHero(String customerId, String planTier) {
boolean showV2 = posthog.isFeatureEnabled(
"pricing_hero_v2",
customerId,
Map.of("plan", planTier));
posthog.capture(customerId, "pricing_hero_resolved",
Map.of("variant", showV2 ? "v2" : "control"));
return showV2 ? PricingHero.VARIANT_B : PricingHero.CONTROL;
}
Python integration — BIN velocity worker shares the fraud tree
import os
from kiponos import Kiponos
os.environ["KIPONOS_PROFILE"] = "['fintech']['auth']['prod']['live']"
kiponos = Kiponos.create_for_current_team()
def detect_bin_attack(transactions: list[dict], target_bin: str) -> bool:
velocity_limit = kiponos.path("fraud", "thresholds").get_int("velocity_per_hour", 20)
multiplier = kiponos.path("fraud", "thresholds").get_float("bin_attack_multiplier", 1.0)
batch_size = kiponos.path("ml", "bin_velocity").get_int("batch_size", 256)
bin_count = sum(1 for t in transactions if t.get("bin") == target_bin)
effective_limit = int(velocity_limit * multiplier)
return bin_count > effective_limit
def on_config_change(change):
if change.path.startswith("fraud/thresholds/block_score"):
log.info("block_score updated to %s", change.new_value)
kiponos.after_value_changed(on_config_change)
PostHog has no natural home for Python BIN velocity workers and Java authorization filters sharing fraud/thresholds/block_score during a card-testing ring — and you should not add ClickHouse pipeline dependencies to either runtime for incident floats.
Real scenarios
| Event | PostHog alone | PostHog + Kiponos |
|---|---|---|
pricing_hero_v2 flag with session replay |
Native analytics suite | Keep PostHog; unchanged |
| BIN attack — lower block score on auth path | Analytics SDK on 15k TPS filter |
fraud/thresholds/block_score local read |
| Processor outage — tighten circuit | Flag payload + fake system identity |
resilience/payments/failure_rate_threshold immediate |
| Flash sale — raise Tomcat threads | Not the tool; no replay needed |
runtime/tomcat/max_threads with live bind |
| Python + Java aligned fraud thresholds | Duplicate flag definitions | One Kiponos profile, two SDKs |
| Auth filter must stay analytics-free | Violates architecture | Kiponos embedded SDK — zero capture overhead |
Performance — analytics flags vs ops hub reads
-
PostHog
isFeatureEnabled()— remote evaluation or local cache with analytics coupling — ideal for product surfaces with capture - PostHog on authorization filter — identify buffering, event queue, flag staleness — wrong latency contract at 15k TPS
- Session replay infrastructure — valuable for checkout UX; zero relevance for circuit breaker math
-
Kiponos
getInt()— pure in-memory path walk with no network on hot path - WebSocket deltas — one key change propagates without PostHog flag deploys or pod restarts
- Privacy boundary — auth path stays free of product analytics identifiers; Kiponos carries ops values only
Honest comparison table
| Criterion | PostHog (OSS) | Kiponos | Honest verdict |
|---|---|---|---|
| Product analytics + funnels | Core strength | Not analytics | PostHog for product learning |
| Feature flags + session replay | Integrated suite | Not a replay platform | PostHog wins UX diagnostics |
| Self-hosted all-in-one | Full stack option | Managed hub — evaluate policy | Depends on InfoSec |
| Numeric ops thresholds on auth path | Flag payload workarounds | First-class local reads | Kiponos for money path |
| Nested cross-service config trees | Flat flag keys | Hierarchical paths | Kiponos for platform ops |
| Hot-path read at 15k TPS | Analytics SDK overhead | Local cache, no capture | Kiponos on authorization |
| Live pool / thread tuning | Not designed for this | afterValueChanged binds |
Kiponos for JVM knobs |
| Java + Python same ops hub | Partial | Both SDKs | Kiponos for polyglot ops |
| Cohort multivariate flags | Native | Application concern | PostHog for product |
| Operational cost | ClickHouse + pipeline ops | Team/hub pricing | Scope each system narrowly |
When not to use Kiponos
| Use case | Better tool |
|---|---|
| Product funnels, cohorts, and session replay | PostHog |
| Feature flags tied to analytics events | PostHog |
| Marketing site A/B tests with replay | PostHog |
| Bootstrap secrets and DB passwords | Vault / K8s Secrets |
| Infrastructure desired state | GitOps / Terraform |
Getting started (15 minutes) — keep PostHog for product analytics only
- Audit PostHog flag catalog: mark each as product surface flag vs misplaced ops knob.
-
TeamPro at kiponos.io — profile
['fintech']['auth']['prod']['live']. - Migrate three ops keys off PostHog flags:
block_score,failure_rate_threshold,max_threads. - Wire Java
FraudAuthFilterand Python BIN velocity worker to the same profile; add Tomcat bind hook. - Document RFC: "PostHog owns product analytics and surface flags; Kiponos owns payment/fraud/resilience config trees — no analytics SDK on auth path."
Further reading
- Developer Quickstart
- Product tour
- GETTING-STARTED.md
- Feature flags vs config hub (architecture)
- Kiponos vs Unleash
- Fraud payment routing
- Tomcat max threads Aha
- github.com/kiponos-io/kiponos-io
Kiponos.io — PostHog for what users clicked and which hero they saw. Live hub for how hard fraud blocks without analytics on the auth path.

Top comments (0)