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

Laravel Appkeep Laravel Package

appkeep/laravel-appkeep

appkeep/laravel-appkeep helps you keep your Laravel application healthy and running smoothly. It offers lightweight tools for monitoring, maintenance, and routine upkeep, with easy configuration that fits cleanly into your existing workflow and keeps your project reliably on track.

View on GitHub
Deep Wiki
Context7

Getting Started

Install pinned, not floating. At v0.6.2 this is pre-1.0 software, so an exact pin is the only sane default:

composer require appkeep/laravel-appkeep:0.6.2

Package discovery registers the service provider automatically. Resist ^0.6 until you have read a minor changelog and confirmed it is non-breaking.

Publish the config, then read it end to end. The config file is effectively the documentation for this package — it is where endpoints, check toggles, and keep-alive schedules are defined:

php artisan vendor:publish --provider="AppKeep\AppKeepServiceProvider"

If the tag/provider guess fails, php artisan vendor:publish interactively lists available tags. Copy the published config/appkeep.php into your notes early; it is the contract you are adopting.

Discover the surface area before writing code. The package ships Laravel-native commands, which is the fastest way to learn what it actually does:

php artisan list appkeep
php artisan help appkeep:<command>

Also skim vendor/appkeep/laravel-appkeep/src — the codebase is small enough (a patch release fixed one memory-parsing path) to read in an hour. That hour buys you certainty about whether it registers middleware, routes, or only commands.

First use case: a health endpoint behind an external monitor. Point an uptime service (BetterStack, UptimeRobot, Pingdom) at the package's health route, or at a thin route of your own that calls into it. This is the lowest-risk, highest-value slice: it is read-only, it does not touch the write path, and it gives immediate signal.

First-day checklist:

  1. Confirm the health route is registered: php artisan route:list | grep -i health.
  2. Hit it locally, in staging, and from outside your network.
  3. Verify php artisan config:cache and php artisan route:cache still work with the package enabled.
  4. Confirm no migrations ran (php artisan migrate:status) — you do not want a monitoring package owning schema.

Implementation Patterns

Split liveness from readiness. A single /health that checks DB, Redis, queue, and disk is an outage amplifier: one degraded optional dependency turns your load balancer red and takes down a working app. Pattern:

  • /up — returns 200 if PHP is executing. Nothing else. Use this for the load balancer and container healthcheck.
  • /health — the richer appkeep report (DB, cache, queue depth). Use this for dashboards and alerting, not for routing traffic.

If the package only exposes the deep check, wrap it: keep its route on an internal-only hostname or behind a signed URL, and hand-roll the trivial liveness route.

Keep-alive scheduling: register it, then verify it fires. Cold starts on serverless containers and idle-dropped connections on PaaS are the real target here. Register the keep-alive command in routes/console.php (Laravel 11+) or the scheduler in app/Console/Kernel.php:

Schedule::command('appkeep:keep-alive')->everyFiveMinutes()->withoutOverlapping();

Then verify empirically — do not trust the registration:

php artisan schedule:list
php artisan schedule:run -v   # run manually, watch output

Check your schedule:list output against reality after every deploy. A keep-alive task that silently stops running is worse than none, because your dashboards still look green.

Queue health: probe by round-trip, not by connection. A "can I connect to Redis" check passes while workers are dead. The pattern that actually catches failure is a heartbeat job: a scheduled task dispatches a tiny job, the job writes cache()->put('queue.heartbeat', now(), 3600), and the health check asserts that timestamp is fresh. Anything older than N minutes means the worker pool is stalled.

// in your health check
$beat = cache()->get('queue.heartbeat');
abort_if(! $beat || $beat->lt(now()->subMinutes(10)), 503, 'Queue stalled');

Use appkeep's queue check as a first pass, and this heartbeat as the check you actually page on.

Scheduler health has a chicken-and-egg problem. If cron dies, the scheduler dies, and any scheduler-based self-check dies with it. The only reliable pattern is external: have your keep-alive command curl an external dead-man's-switch URL (healthchecks.io, Cronitor). If the pings stop, the external service alerts you. appkeep can be the thing that pings, but it cannot be the thing that notices the pinging stopped.

Capture specs into your support tooling, not just a dashboard. The SpecContext component (memory limit, environment facts) is most valuable as context attached to error reports. Pattern: in your exception handler's report() path, or on a Log::withContext() call at boot, inject the captured specs. Now every Sentry/Bugsnag issue arrives with the PHP memory limit and environment attached — which is exactly the class of question you otherwise ask a user in a support thread.

Wrap it behind your own interface. With a single maintainer and pre-1.0 semver, the cheapest insurance is a one-file abstraction:

interface HealthReporter {
    public function check(): array; // ['ok' => bool, 'checks' => [...]]
}

Bind an adapter to the package. When 0.7 breaks an API or the package stalls, you swap one class instead of grepping your codebase. This costs an hour and is the highest-ROI thing you will do with this dependency.

Gate it by environment config, not by hard removal. Put a APPKEEP_ENABLED flag in config/appkeep.php. Local and CI get the cheap checks; production gets the full set. Remember env() only works inside config files once you run config:cache.

CI pattern: add a job that boots the app with the package installed on your full PHP matrix (8.1/8.2/8.3) and asserts the health endpoint returns 200 and includes the spec payload. That is the test that catches the failure mode this package has already demonstrated once — an environment-detection regression.

Gotchas and Tips

PHP 7.4 memory parsing is the known weak spot. v0.6.2 fixed SpecContext failing to read memory size on PHP 7.4. That tells you two things: memory_limit string parsing (128M, -1 for unlimited, 0, -1G) is a code path with a history of edge cases, and it is not necessarily regression-tested. If you rely on the memory spec, write your own test asserting it resolves correctly for your actual memory_limit values. Treat -1 specifically — unlimited memory is the value most likely to produce a nonsense number or a null.

Do not expose the deep health payload publicly. Health endpoints routinely leak PHP version, Laravel version, extension list, DB driver, queue backend, and sometimes env-adjacent detail. That is a reconnaissance gift. Options, in order of preference: bind the route to an internal-only interface, put it behind a shared secret header, or return only a boolean and log the detail. Verify with curl from an external network before you call it done.

Every check in the health path needs a timeout. A DB check without a connect timeout will hang your health endpoint exactly when the database is slowest — which is precisely when the monitor needs an answer. A monitor that times out is indistinguishable from a monitor that got a 500, and you will spend an incident debugging the wrong layer.

Config caching will surprise you. Publish config, edit it, forget php artisan config:cache, and you will debug a stale value for twenty minutes. Conversely, if you edit config after caching, nothing changes until you re-cache. Add config:cache and config:clear to your deployment script explicitly and verify the health route after each deploy.

Serverless has no cron. The scheduled keep-alive pattern in this package assumes a running scheduler. On Vapor, Lambda, or Cloud Run scale-to-zero, you need an external trigger (EventBridge, Cloud Scheduler) hitting your keep-alive route. Without it, the package's scheduled tasks simply never execute and you get silence, not errors.

Debugging checklist when a check misbehaves:

  • php artisan route:list — is the route actually there, and on the verb you expect?
  • php artisan about — confirm cached config/broadcasting/etc. state.
  • php artisan list appkeep — confirm command signatures; they may have changed in a minor.
  • php artisan tinker — invoke the check class directly and inspect the raw result, bypassing HTTP.
  • Check the log channel: monitoring packages often log failures rather than throwing, so a broken check can look like a passing one.

"Fails silently" is the default risk with health checks. Confirm that a failing check actually returns a non-2xx status, not a 200 with a JSON body saying "status": "degraded". Most uptime monitors only look at the status code. Run the endpoint with a dependency deliberately stopped (drop the DB, flush Redis in a dev environment) and confirm the monitor turns red. Do this once, on purpose, before you trust it.

Extension points, in likely order of usefulness: the published config (toggle checks and schedules), the route definition (if publishable, override the path and middleware), the command classes (subclass a check if the contract is public), and your own HealthReporter adapter (always available). Prefer the adapter — it survives minor releases.

Pin, read the changelog, and set a decision trigger. Every 0.x minor can break you. The cheap discipline: exact pin in composer.json, read the release notes on every bump, and write down now what makes you keep or drop this — for example, "reassess at 1.0" or "drop if it is unreferenced for two quarters." With one GitHub org and no LTS commitment, an unexamined dependency is the one that hurts later.

Keep it off the critical request path. Nothing here belongs in middleware that runs on every request or in the deploy sequence's blocking steps. Monitoring should observe the application; the moment it can fail the application, you have added a dependency whose failure mode is an outage you were trying to prevent.

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