Skip to content

15. Configuration reference ​

Publish the file with php artisan vendor:publish --tag=laragraph-config. Every key is optional; the defaults are shown. For a complete, working configuration, see example/config/laragraph.php.

default_schema ​

php
'default_schema' => 'default',

The schema served at /graphql and used by Laragraph::execute() when you don't name one. It must be a key of schemas.

auth ​

php
'auth' => [
    'default_guard' => null,
],
KeyDefaultMeaning
default_guardnullThe guard used by authorizeWithContext(), policy(), the per-user response cache and subscriber identities, when a field doesn't declare guards(). null means Laravel's default guard. See Authentication.

discover ​

php
'discover' => [
    'types'         => 'app/GraphQL/Types',
    'queries'       => 'app/GraphQL/Queries',
    'mutations'     => 'app/GraphQL/Mutations',
    'subscriptions' => 'app/GraphQL/Subscriptions',
],

Directories (relative to the project root) that are scanned recursively for classes extending the matching base class. Set a key to '' to turn off discovery for that category. Discovered fields and types belong to every schema (see Multiple schemas). Cache the result in production with laragraph:cache.

route ​

php
'route' => [
    'prefix'     => 'graphql',
    'middleware' => [],
    'methods'    => ['GET', 'POST'],
],
KeyMeaning
prefixURL prefix of every Laragraph route
middlewareRoute middleware for all Laragraph routes, including GraphiQL and unsubscribe (e.g. ['throttle:api'])
methodsHTTP methods for schema endpoints that don't set their own method

schemas ​

php
'schemas' => [
    'default' => [
        'query'        => [],   // 'fieldName' => QueryClass::class
        'mutation'     => [],
        'subscription' => [],
        'types'        => [],   // 'Alias' => TypeClass::class, only in this schema
        'middleware'   => [],   // route middleware for this schema's endpoint
        'method'       => ['GET', 'POST'],
    ],
],

See Multiple schemas.

types ​

php
'types' => [
    'DateTime' => \Ayimdomnic\Laragraph\Scalars\DateTimeType::class,
    'Date'     => \Ayimdomnic\Laragraph\Scalars\DateType::class,
    'JSON'     => \Ayimdomnic\Laragraph\Scalars\JsonType::class,
    'Upload'   => \Ayimdomnic\Laragraph\Scalars\UploadType::class,
    'UserRole' => \App\Enums\UserRole::class,     // native PHP enums work too
],

Types registered for every schema. Use it for scalars, enums and any type outside the discovery directories. See Types → Registering types.

error_formatter and errors_handler ​

php
'error_formatter' => [\Ayimdomnic\Laragraph\Laragraph::class, 'formatError'],
'errors_handler'  => [\Ayimdomnic\Laragraph\Laragraph::class, 'handleErrors'],

error_formatter(Error $error): array formats each error. errors_handler(array $errors, callable $formatter): array receives the whole list. Use array callables (not closures) so config:cache works. See Custom error formatting.

errors ​

php
'errors' => [
    'negotiate_locale'  => false,
    'supported_locales' => ['en'],
    'locale_resolver'   => null,
],

Controls per-request error localization; disabled by default (zero overhead — one config() call per request). See Error Handling & Localization.

security ​

php
'security' => [
    'query_max_complexity'  => 500,
    'query_max_depth'       => 15,
    'disable_introspection' => null,
    'max_aliases'           => 30,
],
KeyMeaning
query_max_complexityMaximum total field cost per operation. null disables it.
query_max_depthMaximum selection nesting. The introspection query needs 11. null disables it.
disable_introspectionnull = disabled while app.debug is off; true/false forces it either way
max_aliasesMaximum aliases per document. null disables it.

See Security.

validation ​

php
'validation' => [
    'rules' => [],   // FQCNs of GraphQL\Validator\Rules\ValidationRule classes
],

Extra document validation rules, resolved from the container and run on every operation. A rule of the same class as a built-in rule replaces it. Also available at runtime: Laragraph::addValidationRule().

pagination ​

php
'pagination' => [
    'per_page'     => 15,
    'max_per_page' => 100,
],
KeyMeaning
per_pagePage size when the client sends neither first nor last (or per_page)
max_per_pageUpper bound for any requested page size. null = no cap.

cache ​

php
'cache' => [
    'response' => [
        'enabled' => false,
        'store'   => 'default',
        'ttl'     => 60,
        'scope'   => 'user',
    ],
],
KeyMeaning
enabledCache results of query operations
storeCache store name; 'default' = cache.default
ttlSeconds
scope'user': one partition per user (on auth.default_guard) plus one shared guest partition. 'global': shared by everyone.

See Performance & caching.

persisted_queries ​

php
'persisted_queries' => [
    'enabled' => false,
    'store'   => 'cache',
    'ttl'     => 3600,
    'map'     => [],
    'apq'     => true,
    'only'    => false,
],
KeyMeaning
enabledAccept queryId and APQ extensions.persistedQuery requests
store'cache' (default cache store, supports runtime registration) or 'array' (the static map)
ttlLifetime of cache-stored queries in seconds; null = forever
mapid => query pairs for the array store. Key them by SHA-256 hash for trusted-documents mode.
apqStore a query when a client sends it together with its hash
onlyTrusted documents: execute only query text already stored under its hash

See Persisted queries.

extensions ​

php
'extensions' => [
    'request_id'       => false,
    'query_timing'     => false,
    'query_complexity' => false,
],

Add extensions.requestId.id, extensions.timing.execution_ms, and extensions.queryComplexity.{cost,maxCost} (empty unless security.query_max_complexity is set) to every response. Register custom extensions with ExtensionRegistry::add(). See Observability.

middleware ​

php
'middleware' => [],

Field middleware applied to every root field (queries, mutations, subscriptions), before the field's own middleware(). Entries are class names (resolved from the container) or instances of FieldMiddlewareInterface. See Field middleware.

logging ​

php
'logging' => [
    'channel' => null,
],

The log channel used by LoggingMiddleware and by the log subscription driver. null means the default channel.

log_unresolved_fields ​

php
'log_unresolved_fields' => null,

null (default): warn when a field with no resolve{Field}Field() method resolves to null because nothing matched — no model attribute, no array key — following app.debug (loud in development, silent in production). true/false overrides that either way. Logged to logging.channel, not thrown — a resolver mistake shouldn't turn into a 500. See Types → Common mistakes.

database_types ​

php
'database_types' => [
    'preset' => null,   // 'postgres', 'cockroachdb', 'mssql', 'oracle'
    'custom' => [],     // 'Name' => ScalarClass::class
],

Register scalars for native column types:

PresetScalars
postgresUUID, BigInt, JSONB, Money, TSVector, Interval, Inet
cockroachdbUUID, BigInt, JSONB, Inet
mssqlUUID, BigInt, Money
oracleUUID, BigInt, Interval

See Types → Database scalar presets.

batching ​

php
'batching' => [
    'enabled'        => false,
    'max_operations' => 10,
],

Accept a JSON list of operations per request. max_operations of 0 removes the limit. See Batching.

graphiql ​

php
'graphiql' => [
    'enabled'    => null,
    'middleware' => [],
    'title'      => 'Laragraph — GraphiQL',
],
KeyMeaning
enablednull = served only while app.debug is on; true = always; false = never
middlewareRoute middleware for the GraphiQL page, e.g. ['web', 'auth', 'can:viewGraphiql']
titlePage title

tracing ​

php
'tracing' => [
    'enabled' => false,
    'driver'  => 'apollo',  // or 'otel'
    'otel'    => ['tracer_name' => 'laragraph'],
],

Resolver timings, 'apollo' (default) under extensions.tracing, 'otel' exported as real OpenTelemetry spans instead. Development only. See Tracing.

octane ​

php
'octane' => [
    'warm' => true,
],

Under Laravel Octane, add Laragraph to octane.warm so each worker compiles the schema and validates each document once, instead of on every request. false leaves Octane's warm list alone. See Performance → Octane.

subscriptions ​

php
'subscriptions' => [
    'enabled'           => false,
    'driver'            => 'broadcast',
    'cache_store'       => null,
    'ttl'               => 3600,
    'channel_prefix'    => 'graphql-subscriber',
    'authorize_channel' => true,
    'queue' => [
        'connection' => null,
        'queue'      => null,
    ],
    'sse' => [
        'max_duration'      => 30,
        'poll_interval_ms'  => 500,
        'heartbeat_seconds' => 15,
    ],
],
KeyMeaning
enabledAccept subscription operations. When off, they're rejected with an error.
driver'broadcast' (Laravel Broadcasting), 'log' (write updates to logging.channel), or 'sse' (plain HTTP Server-Sent Events, no broadcaster needed)
cache_storeWhere subscriber registrations are stored; must be shared between servers. null = default store.
ttlLifetime of a registration in seconds
channel_prefixPrivate channel each subscriber listens on: {prefix}.{subscriberId} ('broadcast' driver)
authorize_channelRegister the rule that lets only the subscriber join their channel. false = write your own in routes/channels.php.
queue.connection / queue.queueWhere broadcastLater() queues its job. null = application defaults.
sse.max_durationSeconds before an open 'sse'-driver connection self-closes (the client's EventSource reconnects transparently)
sse.poll_interval_msHow often an open connection checks for a new pending message
sse.heartbeat_secondsHow often an SSE comment is sent on an otherwise idle connection, so proxies don't time it out

See Subscriptions — read the 'sse' driver's capacity note before relying on it for more than a handful of concurrent subscribers.

Released under the MIT License.