posthog-js-lite
posthog-js-lite copied to clipboard
Events lost when submitting multiple events and using `flushAt: 1, flushInterval: 0`
Bug description
posthog-node
running in a Next.js app router app configured with flushAt: 1, flushInterval: 0
as recommended seems to lose events that are issued in batches.
We have a Next.js 14.2.3 App Router app that includes a batch job (invoked via an API request) that pulls a list of PostHog events and possibly distributes rewards points to users based on those events. The general form of the batch job is attached in additional context below.
When run with slightly non-trivial amounts of data (e.g., 50-100 input events), posthog-node
seems only to submit some of them, as indicated by the data visible on posthog.com and message list passed to posthog.on('flush', (...args) => { console.log('PostHog flush', ...args); })
.
The issue can be worked around by creating a custom instance of posthog-node
with no flushAt: 1, flushInterval: 0
parameters.
How to reproduce
This is probably the bare minimum information for a reproduction — please let me know if you need a sample repo.
- Create a Next.js 14.2 app router app, configure a posthog instance with recommended parameters, and set up a batch job that captures a number of events while processing input in a loop.
- Set up instrumentation to catch
capture
,flush
, anderror
events emitted by the posthog instance. - Run the batch job.
- Verify that no errors occurred and there are no additional console output (e.g., no "queue is full" messages).
Expected: All events that have triggered a capture
event also appear in the flush
event, and all events are visible in PostHog.
Observed: Some captured events are not submitted to PostHog and don't appear in flush
event logs.
Related sub-libraries
- [ ] All of them
- [ ] posthog-web
- [x] posthog-node 4.0.1
- [ ] posthog-react-native
Additional context
Sample batch job flow
export async function distributeWelcomeBonuses() {
const { results } = await queryPostHog(
HOGQL_QUERY,
{ now: new Date().toISOString() },
RESULTS_SCHEMA,
{
host: env.NEXT_PUBLIC_POSTHOG_HOST,
projectId: env.POSTHOG_PROJECT_ID,
apiKey: env.POSTHOG_READ_API_KEY,
},
);
for (const row of results) {
const { userId, triggerEventKey } = row;
const shouldReward = Math.random() < 0.8; // some logic
if (shouldReward) {
// insert a reward transaction into the database
await createEarnPointsTransaction(dbClient, {
userId: userId,
amount: REWARD_AMOUNT,
reason: POINTS_AWARDED_REASON,
internalNote: `${triggerEventKey.event} - ${env.NEXT_PUBLIC_POSTHOG_HOST}/project/${env.POSTHOG_PROJECT_ID}/events/${triggerEventKey.uuid}/${triggerEventKey.timestamp}`,
eventKey: triggerEventKey,
});
posthog.capture({
distinctId: userId.toString(),
event: POINTS_AWARDED_EVENT,
properties: {
reward_reason: POINTS_AWARDED_REASON,
reward_amount: REWARD_AMOUNT,
reward_trigger_event: triggerEventKey,
},
});
}
}
await posthog.flush();
}