Hidden Assumptions in openreplay
13 assumptions this code never checks · 5 critical · spanning Ordering, Temporal, Resource, Scale, Environment, Domain, Contract, Shape
Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at openreplay/openreplay and picked out the few most likely to cause trouble. The full list is just below.
Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".
If Kafka partitioning fails or messages for a session arrive across multiple partitions, the session timeout logic will see events out of order, potentially ending sessions prematurely or extending them incorrectly, corrupting session duration metrics
Sessions for mobile apps with background behavior or slow networks get artificially terminated early, while bot traffic or automated tests create artificially long sessions, skewing analytics and potentially losing real user data
Asset caching grows unbounded over time, eventually exhausting disk space and causing the entire asset service to fail, breaking session replay functionality when screenshots and source maps can't be retrieved
Show everything (10 more)
The MessageSizeLimit configuration adequately handles the largest possible user interactions, but there's no validation that message producers respect this limit or that downstream consumers can handle messages approaching this size
If this fails: Large DOM mutations or massive JavaScript payloads exceed the limit, causing message rejection at Kafka ingestion but silent data loss since the application continues processing without the oversized events, resulting in incomplete session replays
backend/cmd/db/main.go:cfg.MessageSizeLimit
The process.env.maxHttpBufferSize environment variable, if present, contains a valid numeric value that can be parsed as a float and converted to bytes by multiplying by 1e6
If this fails: If maxHttpBufferSize contains non-numeric data, parseFloat returns NaN, causing WebSocket connections to use NaN * 1e6 as buffer size, which becomes 0 bytes, immediately dropping all real-time assistance data and breaking live support features
assist/utils/wsServer.js:createSocketIOServer
ClickHouse event records always contain the expected performance timing properties (dom_content_loaded_event_time, first_contentful_paint_time, etc.) as valid numeric strings that can be cast to Float32
If this fails: If browser events omit timing data or send non-numeric values (like 'undefined' or null), the CAST operations produce null values that NULLIF removes, causing performance alert thresholds to evaluate against incomplete data and miss critical performance regressions
api/chalicelib/core/alerts/alerts_processor.py:LeftToDb
All binary message data passed to the canvas image iterator contains valid message headers with correctly formatted message types and session IDs that can be deserialized by messages.ReadMessage()
If this fails: Malformed binary data from network corruption or version mismatches causes ReadMessage to panic, crashing the entire canvas service and preventing screenshot generation for all sessions until the service restarts
backend/cmd/canvases/main.go:messages.NewImagesMessageIterator
Message timestamps in the stream represent the actual time when user events occurred in the browser, not when they were processed by the backend, allowing accurate session timeout calculations
If this fails: Network delays or message queue backlogs cause timestamps to represent processing time rather than event time, making session timeouts fire based on system lag rather than user inactivity, incorrectly ending active sessions during high load
backend/cmd/ender/main.go:sessionEndGenerator.UpdateSession
A 20-minute cleanup interval is sufficient to prevent memory leaks from accumulated asset cache entries, and the system can handle all cleanup operations within a single 20-minute window
If this fails: During high traffic periods with many unique URLs, memory usage grows faster than the 20-minute cleanup can process, eventually causing out-of-memory crashes in the assets service and losing cached data needed for session replay
backend/cmd/assets/main.go:tick = time.Tick(20 * time.Minute)
All Message structs deserialized from Kafka contain session IDs that exist as valid sessions in the sessions manager and can be looked up without error
If this fails: Race conditions where messages arrive after a session is deleted from Redis cause datasaver to fail session lookups, dropping events for recently ended sessions and creating gaps in session replay data near session boundaries
backend/internal/db/datasaver/datasaver.go:saver processing
The JWT secret key is provided through configuration and contains sufficient entropy to prevent brute force attacks, but there's no validation of key strength or rotation requirements
If this fails: Weak or default JWT secrets allow attackers to forge authentication tokens, gaining unauthorized access to session data and user recordings from any project in the system
backend/cmd/api/main.go:cfg.JWTSecret
The hardcoded msgFilter array contains all message types that the datasaver needs to process, and this list remains synchronized with message types generated by the tracker without any automated verification
If this fails: When new message types are added to the tracker, they won't be filtered into the database consumer, causing new event data to be silently ignored and creating incomplete session replays missing the newest interaction types
backend/cmd/db/main.go:queue.NewConsumer msgFilter
The number of concurrent WebSocket connections per room stays within Socket.IO's default memory limits, and room-based operations complete within reasonable time bounds
If this fails: Large assistance sessions with many concurrent agents cause fetchSockets() operations to timeout or consume excessive memory, degrading performance for all assistance sessions and potentially causing the entire assist service to become unresponsive
assist/utils/wsServer.js:io.in(roomID).fetchSockets()
See the full structural analysis of openreplay: the pipeline, data models, and system behavior that put these assumptions in context.
Full analysis of openreplay/openreplay →Frequently Asked Questions
What does openreplay assume that could break in production?
The one most likely to cause trouble: Kafka partitions for each session maintain message ordering and all messages for a session flow through the same partition, allowing sessionEndGenerator.UpdateSession() to process events in chronological order If this fails, If Kafka partitioning fails or messages for a session arrive across multiple partitions, the session timeout logic will see events out of order, potentially ending sessions prematurely or extending them incorrectly, corrupting session duration metrics
How many hidden assumptions does openreplay have?
CodeSea found 13 assumptions openreplay relies on but never validates, 5 of them critical, spanning Ordering, Temporal, Resource, Scale, Environment, Domain, Contract, Shape. Most are routine — the analysis flags the two or three most likely to actually bite.
What is a hidden assumption?
Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.