Measuring FeathersJS Hook Latency Before Placement Decision
0 reputation · 21 May 2024, 18:19 UTC
0 reputation · 21 May 2024, 18:19 UTC
We want to measure the latency impact of a custom hook before deciding where to place it in the hook chain.
Hooks run in the order defined for each service method (before, after, error). A hook that performs heavy asynchronous work can increase response time, while a hook that throws early aborts the chain. The hook context exposes parameters, result, and metadata, allowing conditional logic but also potential side effects.
Given a hook that logs request details and updates a cache, should it be attached to the before or after phase of the create method? The choice affects whether the logging occurs before the database write (potentially missing the final result) or after (introducing extra round‑trip latency).
30275 reputation · 22 May 2024, 00:17 UTC
To measure a hook’s latency, wrap its body with a high‑resolution timer (e.g., process.hrtime.bigint()) and store the elapsed time in context.meta; alternatively, run the service with the hook enabled and disabled under identical load and compare p50/p95 response times. For a hook that logs and updates a cache, place the cache update in the after phase of create when you need the final record; if the cache write must be awaited before sending the response, this adds latency, otherwise you can fire‑and‑forget it. Splitting the logic into two hooks (logger and cache updater) is safer and lets you order them independently.
process.hrtime.bigint() before and after the hook call.context.meta.hookLatency.context.meta.autocannon) with the hook enabled and then disabled; the difference in p50/p95 latency approximates the hook’s cost.before phase runs before the database write, so context.result is not yet available.after phase runs after the write, providing context.result (including generated IDs).after to use the final record.after adds network latency; you can make it fire‑and‑forget with error handling to avoid blocking the response.before risks writing a cache entry that may become stale if the database write fails.Separating concerns into two hooks improves clarity and safety:
before (or early in after) to record request metadata; it can be fire‑and‑forget if logging is non‑critical.after where context.result is available; await it only if strong consistency is required, otherwise fire‑and‑forget with error handling.Example registration:
app.service('items').hooks({
before: { create: [logHook] },
after: { create: [cacheHook] }
});
To finalize the recommendation, please confirm whether the cache update must be awaited before the response is sent (i.e., strong consistency) or can be performed asynchronously.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.