Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Clickhouse Laravel Laravel Package

lucasacoutinho/clickhouse-laravel

ClickHouse integration for Laravel that connects your app to the ClickHouse columnar database using familiar query builder and Eloquent-style syntax, making it easy to run fast analytics queries and store large volumes of event data alongside your existing application.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

  • The package occupies a familiar Laravel slot: a service provider that merges and publishes a config file, with behaviour driven by environment variables. This is the lowest-friction integration pattern in the Laravel ecosystem and requires no changes to application layering — repositories, jobs, and console commands can consume ClickHouse without adopting a new architectural style.
  • The change in v1.3.1 makes the buffering layer configurable through the standard config/*.php + .env convention. For a TPM this is a positive signal: tuning knobs are exposed through the same mechanism as database, queue, and cache settings, which means existing deployment templates, secret managers, and config-drift tooling apply unchanged.
  • Buffered inserts imply an in-process accumulator rather than per-row writes. That is the correct design for ClickHouse (which penalises small, frequent inserts), but it introduces statefulness into the PHP worker. This is the single most consequential architectural fact for planning purposes.

Integration feasibility

  • Integration effort is low: composer require, publish config, set two environment variables, and the feature is live. There is no schema migration, no new infrastructure beyond the ClickHouse endpoint itself, and no required changes to existing models unless the team wants to dual-write.
  • The two limits map cleanly onto a single operational decision: how much memory is a PHP process allowed to hold before it must flush. That is a conversation a TPM can hold with infrastructure and product without deep library knowledge, which is unusual and valuable.
  • The defaults (1,000,000 rows / 64 MiB inherited from PDO) mean a team can ship without setting anything, but the defaults are almost certainly too high for typical FPM or Octane worker memory budgets.

Technical risk

  • Memory amplification. A 64 MiB default buffer is per-buffer, not per-application. With 20 FPM workers or 8 Octane workers, worst-case resident memory attributable to buffering is measured in gigabytes. This risk is invisible until load testing, which is exactly when it is most expensive to discover.
  • Patch-version behavioural change. v1.3.1 is a patch release, but it changes the config contract: installations that previously published a config file with literal integers must re-publish or hand-edit, and any environment overriding those keys now takes effect where it previously did not. Environments that already set unrelated variables with similar names could be silently misread.
  • Validation timing is unspecified. The notes state explicit values must be positive integers but do not say whether that is enforced at config-load (boot-time exception) or at flush time (runtime exception). The difference between a failed deploy and a failed request is significant for rollback planning.
  • Empty-string ambiguity. env() returns an empty string for a key defined as empty, which casts to 0 under a naive integer cast. Whether that is caught by the positive-integer check, or silently disables the limit, is unconfirmed.

Key questions

  1. Which transport underlies the buffer — PDO, HTTP, or a native client — and are the two limits enforced per-connection, per-process, or per-flush?
  2. Is the buffer flushed on request termination, on a timer, or only on threshold? What happens to unflushed rows on a fatal error or SIGTERM during deploy?
  3. Where is positive-integer validation performed, and what is the failure mode (exception at boot vs. at write time)?
  4. Are the limits read once at boot or re-read per flush? This determines whether .env changes require a full restart.
  5. Does the package have first-class support for Laravel Octane and queue workers, where long-lived processes make buffer accumulation materially different from FPM?
  6. What observability exists — flush counts, buffer depth, dropped rows, flush latency?
  7. Is there a synchronous, unbuffered escape hatch for correctness-critical writes where loss is unacceptable?

Integration Approach

Stack fit

  • Assumes a conventional Laravel application with MySQL/Postgres as the transactional store and ClickHouse as the analytical store. The package supports the read-path (analytics queries) and the write-path (buffered ingestion) without requiring the application to adopt an event-streaming platform.
  • Fits cleanly into existing config management: the two variables belong in the same .env/secrets tier as DB_* and QUEUE_*, and should be present in every environment's template, including local.
  • Teams already using a queue worker tier have a natural home for buffered writes; teams relying purely on synchronous request handling should treat buffering as a deliberate, separately-reasoned decision.

Migration path

  • Fresh installs: publish config, set explicit values, ship. No ambiguity.
  • Existing installs upgrading to v1.3.1: the published config file must be re-published (vendor:publish --force) or manually patched to replace the literal integers with env() calls. Because this arrives in a patch release, it will likely be pulled in by an unpinned composer update — flag this for whoever owns dependency hygiene.
  • No data migration is required. No schema changes, no dual-write cutover, no backfill. This is a configuration-only upgrade and can be reversed by reverting the config file.
  • Recommend pinning the exact version during rollout rather than accepting the floating constraint, precisely because a patch changed configuration semantics.

Compatibility

  • Laravel/PHP version support is not stated in the release notes and must be confirmed against composer.json before committing. The env() helper and config-publishing pattern are stable across Laravel 8–11, so the risk here is low but non-zero.
  • Interaction with config caching (php artisan config:cache) should be verified: cached config freezes the resolved values, so .env edits after a cache warm will not take effect. This is a standard Laravel behaviour but is a frequent source of "the tuning didn't apply" incidents.
  • Octane and queue-worker compatibility is the material unknown and should be validated explicitly rather than assumed.

Sequencing

  1. Verify compatibility — confirm Laravel/PHP constraints and whether Octane/queue workers are supported.
  2. Size the buffer — derive max_buffered_bytes from the per-worker memory budget, not from the library default. Set max_buffered_rows as the secondary guard.
  3. Publish and pin config in staging; set both variables explicitly in every environment template, including the values that match the defaults, so behaviour is stated rather than inherited.
  4. Load test at realistic concurrency and observe peak RSS per worker and flush failure rates.
  5. Roll to production behind the existing deploy process, with the config change isolated in its own commit so it can be reverted independently of application code.
  6. Instrument before optimising — establish flush/error metrics before tuning the limits further.

Operational Impact

Maintenance

  • Ongoing burden is low but non-zero: two new environment variables must be kept consistent across local, CI, staging, and production. Drift between environments is the most likely recurring annoyance, and the failure will present as a performance or memory anomaly rather than a clear error.
  • Config-cache warm steps in the deploy pipeline must run after environment variables are set, or the values will not be picked up.
  • Budget a small amount of recurring attention for version bumps: a patch release already changed the config contract once.

Support

  • The tuning question ("what should these be set to?") will recur and should be answered once in a runbook rather than per-incident. Frame it as: bytes ≈ per-worker memory headroom ÷ safety factor; rows as a secondary cap for very wide or very narrow payloads.
  • Support burden is concentrated in one scenario: a developer copies a production .env locally, or omits the variables locally, and observes different flush behaviour than production. Documenting the defaults in the team wiki removes most of this.
  • No new on-call surface is introduced if the buffer is drained reliably at request/worker shutdown. If it is not, this becomes a data-loss paging path.

Scaling

  • Scaling behaviour is inverse to the usual story: more workers do not simply add throughput, they multiply worst-case buffer memory. Horizontal scaling therefore has a memory cost that must be modelled alongside CPU.
  • Setting byte limits low enough for a large worker pool may produce frequent small flushes, degrading ClickHouse insert efficiency. There is a genuine three-way tension between worker count, memory budget, and insert batching — worth resolving with a load test rather than by intuition.
  • Because limits are config-driven, capacity can be tuned per-environment without a code change, which is the right lever to have.

Failure modes

  • Boot-time validation failure — a malformed or empty value prevents the application from starting. Highly visible, fast to diagnose, easy to roll back. The preferred failure mode.
  • Runtime validation failure — writes fail after a request is already in flight. Harder to attribute; requires good logging.
  • Silent limit disablement — an empty string casting to 0 and being treated as "no limit" instead of "invalid" would be the worst outcome. Confirm this is explicitly rejected.
  • Unflushed buffer loss — a fatal error, SIGTERM during deploy, or worker timeout discards accumulated rows. Mitigation is graceful-shutdown handling and, for correctness-critical writes, an unbuffered path.
  • Memory exhaustion — the default 64 MiB combined with a large worker pool, surfacing as OOM kills rather than application errors. This is the highest-likelihood incident and the strongest argument for setting explicit, conservative values from day one.

Ramp-up

  • Engineering ramp-up is measured in hours: the pattern is idiomatic Laravel and requires no new mental model beyond "this writes in batches."
  • TPM ramp-up is similarly light: the decisions reduce to buffer sizing, environment parity, and confirming flush durability — all tractable conversations with infrastructure and the owning engineer.
  • The main knowledge gap to close before committing is durability: the team should be able to state, in one sentence, what happens to buffered rows on an unclean termination. Until that sentence exists, treat the package as suitable for analytics and telemetry, and not yet validated for writes the business cannot afford to lose.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle