PHPackages                             thesis/grpc-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. thesis/grpc-client

ActiveLibrary[HTTP &amp; Networking](/categories/http)

thesis/grpc-client
==================

Async gRPC client for PHP with HTTP/2 transport, streaming RPCs, interceptors, TLS/mTLS, and client-side load balancing.

0.1.7(1mo ago)0222MITPHPPHP ^8.4CI failing

Since Apr 10Pushed 1mo agoCompare

[ Source](https://github.com/thesis-php/grpc-client)[ Packagist](https://packagist.org/packages/thesis/grpc-client)[ Fund](https://www.tinkoff.ru/cf/5MqZQas2dk7)[ RSS](/packages/thesis-grpc-client/feed)WikiDiscussions 0.1.x Synced 1w ago

READMEChangelog (5)Dependencies (6)Versions (7)Used By (2)

thesis/grpc-client
==================

[](#thesisgrpc-client)

> Read-only subtree split from `https://github.com/thesis-php/grpc`.
>
> Do not open issues/PRs here. Use the monorepo:
>
> -
> -

Async gRPC client for PHP with HTTP/2 transport, streaming RPCs, interceptors, TLS/mTLS, and client-side load balancing.

Contents
--------

[](#contents)

- [Installation](#installation)
- [Requirements](#requirements)
- [Basic usage](#basic-usage)
- [TLS and mTLS](#tls-and-mtls)
- [Target addressing](#target-addressing)
- [Load balancing](#load-balancing)
- [Endpoint resolution](#endpoint-resolution)
- [Error handling](#error-handling)
- [Compression](#compression)
- [Interceptors](#interceptors)
- [Client streaming](#client-streaming)
- [Server streaming](#server-streaming)
- [Bidirectional streaming](#bidirectional-streaming)
- [Closing the client](#closing-the-client)

Installation
------------

[](#installation)

```
composer require thesis/grpc-client
```

Requirements
------------

[](#requirements)

To generate gRPC client classes from `.proto`, use:

-

Basic usage
-----------

[](#basic-usage)

```
use Auth\Api\V1\AuthenticateRequest;
use Auth\Api\V1\AuthenticationServiceClient;
use Thesis\Grpc\Client;

$client = new AuthenticationServiceClient(
    new Client\Builder()
        ->withHost('dns:///127.0.0.1:50051')
        ->build(),
);

$response = $client->authenticate(new AuthenticateRequest('root', 'secret'));
```

You can pass request metadata too:

```
use Thesis\Grpc\Metadata;

$response = $client->authenticate(
    new AuthenticateRequest('root', 'secret'),
    new Metadata()->with('x-request-id', 'req-123'),
);
```

TLS and mTLS
------------

[](#tls-and-mtls)

```
use Amp\Socket\Certificate;
use Thesis\Grpc\Client;

$client = new Client\Builder()
    ->withTransportCredentials(
        new Client\TransportCredentials()
            ->withCaCert('/certs/ca.crt')
            ->withPeerName('localhost')
            ->withCertificate(new Certificate('/certs/client.crt', '/certs/client.key')), // optional (mTLS)
    )
    ->build();
```

Target addressing
-----------------

[](#target-addressing)

The target string passed to `withHost()` follows gRPC name resolution format: `scheme:endpoint`.

Supported schemes:

SchemeFormatDescription`dns``dns:///host:port` or `dns://authority/host:port`Resolves hostname via DNS. Supports periodic re-resolution based on TTL.`ipv4``ipv4:addr1:port1,addr2:port2`Comma-separated IPv4 addresses, no DNS lookup.`ipv6``ipv6:[addr1]:port1,[addr2]:port2`Comma-separated IPv6 addresses in bracket notation.`unix``unix:///path/to/socket`Connects via Unix domain socket.`passthrough``passthrough:///address`Passes address through as-is without resolution.If scheme is omitted, `dns` is assumed:

```
// Equivalent:
->withHost('my-grpc-server:50051')
->withHost('dns:///my-grpc-server:50051')
```

Use custom DNS server with authority:

```
->withHost('dns://10.0.0.1:53/my-grpc-server:50051')
```

Multi-endpoint target without DNS:

```
->withHost('ipv4:10.0.0.1:50051,10.0.0.2:50051,10.0.0.3:50051')
```

Load balancing
--------------

[](#load-balancing)

When resolution returns multiple addresses, the load balancer picks endpoint per RPC.

Built-in policies:

- `PickFirstFactory` (default): shuffles endpoint list, picks one, and keeps it pinned until it disappears after refresh.
- `RoundRobinFactory`: cycles through all available endpoints.

With DNS targets, resolver can re-resolve by TTL and call balancer `refresh()` with updated endpoints. Re-resolution interval is clamped between minimum and maximum bounds (default 30..300 seconds).

```
use Thesis\Grpc\Client\LoadBalancer\RoundRobinFactory;

$client = new Client\Builder()
    ->withHost('ipv4:10.0.0.1:50051,10.0.0.2:50051')
    ->withLoadBalancer(new RoundRobinFactory())
    ->build();
```

Custom load balancer example:

```
use Random\Randomizer;
use Thesis\Grpc\Client\Endpoint;
use Thesis\Grpc\Client\LoadBalancer;
use Thesis\Grpc\Client\LoadBalancerFactory;
use Thesis\Grpc\Client\PickContext;

final class RandomBalancer implements LoadBalancer
{
    /**
     * @param non-empty-list $endpoints
     */
    public function __construct(
        private array $endpoints,
        private readonly Randomizer $randomizer = new Randomizer(),
    ) {}

    #[\Override]
    public function refresh(array $endpoints): void
    {
        $this->endpoints = $endpoints;
    }

    #[\Override]
    public function pick(PickContext $context): Endpoint
    {
        return $this->endpoints[$this->randomizer->getInt(0, \count($this->endpoints) - 1)];
    }
}

final readonly class RandomBalancerFactory implements LoadBalancerFactory
{
    #[\Override]
    public function name(): string
    {
        return 'random';
    }

    #[\Override]
    public function create(array $endpoints): LoadBalancer
    {
        return new RandomBalancer($endpoints);
    }
}
```

Endpoint resolution
-------------------

[](#endpoint-resolution)

Resolver is selected by target scheme. You can override resolver for a specific scheme:

```
use Amp\Cache\LocalCache;
use Thesis\Grpc\Client\Builder;
use Thesis\Grpc\Client\EndpointResolver\DnsResolver;
use Thesis\Grpc\Client\Scheme;

$client = new Builder()
    ->withHost('dns:///my-grpc-server:50051')
    ->withEndpointResolver(Scheme::Dns, new DnsResolver(
        cache: new LocalCache(),
        minResolveInterval: 60,
        maxResolveInterval: 600,
    ))
    ->build();
```

Default resolvers by scheme:

- `dns` -&gt; `DnsResolver`
- `ipv4`, `ipv6`, `unix` -&gt; `StaticResolver`
- `passthrough` -&gt; `PassthroughResolver`

You can also implement your own `EndpointResolver` for service discovery backends like Consul/etcd.

Error handling
--------------

[](#error-handling)

```
use Thesis\Grpc\InvokeError;

try {
    $response = $client->authenticate(new AuthenticateRequest('root', 'secret'));
} catch (InvokeError $e) {
    dump($e->statusCode, $e->statusMessage, $e->details);
}
```

Compression
-----------

[](#compression)

Compression reduces payload size and is useful for large protobuf messages or bandwidth-constrained links.

```
use Thesis\Grpc\Compression\GzipCompressor;

$client = new Client\Builder()
    ->withCompression(new GzipCompressor())
    ->build();
```

Interceptors
------------

[](#interceptors)

Interceptors let you add cross-cutting logic (auth, logging, tracing, retry, metadata enrichment) without changing service stubs.

```
use Amp\Cancellation;
use Thesis\Grpc\Client;
use Thesis\Grpc\Client\Invoke;
use Thesis\Grpc\ClientStream;
use Thesis\Grpc\Metadata;

final readonly class ClientAuthInterceptor implements Client\Interceptor
{
    #[\Override]
    public function intercept(Invoke $invoke, Metadata $md, Cancellation $cancellation, callable $next): ClientStream
    {
        return $next($invoke, $md->with('Authorization', 'supertoken'), $cancellation);
    }
}
```

Client streaming
----------------

[](#client-streaming)

Use client streaming when you need to send many messages and receive one final aggregated response.

```
use File\Api\V1\Chunk;
use File\Api\V1\FileServiceClient;

$files = new FileServiceClient(new Client\Builder()->build());
$upload = $files->upload();

for ($i = 0; $i < 10; ++$i) {
    $upload->send(new Chunk(random_bytes(10)));
}

$info = $upload->close(); // FileInfo
dump($info->size); // 100
```

Server streaming
----------------

[](#server-streaming)

Use server streaming when a single request should return a sequence of server messages.

```
use Topic\Api\V1\SubscribeRequest;
use Topic\Api\V1\TopicServiceClient;

$topics = new TopicServiceClient(new Client\Builder()->build());
$stream = $topics->subscribe(new SubscribeRequest('payments'));

foreach ($stream as $event) {
    dump($event->name, $event->payload);
}
```

Bidirectional streaming
-----------------------

[](#bidirectional-streaming)

Use bidirectional streaming for conversational protocols where both sides can send messages independently.

```
use Chat\Api\V1\Message;
use Chat\Api\V1\MessengerServiceClient;

$chat = new MessengerServiceClient(new Client\Builder()->build())->chat();

$chat->send(new Message('Hi from gRPC client'));
dump($chat->receive()->text);

$chat->send(new Message('Bye'));
$chat->close();
dump($chat->receive()->text);
```

Closing the client
------------------

[](#closing-the-client)

Call `Client::close()` to stop background resolver activity and release resources, especially when DNS re-resolution is enabled.

```
try {
    $response = $client->authenticate(new AuthenticateRequest('root', 'secret'));
} finally {
    $client->close();
}
```

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance93

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

7

Last Release

36d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2552865?v=4)[Valentin Udaltsov](/maintainers/vudaltsov)[@vudaltsov](https://github.com/vudaltsov)

---

Top Contributors

[![kafkiansky](https://avatars.githubusercontent.com/u/37590388?v=4)](https://github.com/kafkiansky "kafkiansky (5 commits)")

### Embed Badge

![Health badge](/badges/thesis-grpc-client/health.svg)

```
[![Health](https://phpackages.com/badges/thesis-grpc-client/health.svg)](https://phpackages.com/packages/thesis-grpc-client)
```

###  Alternatives

[danog/madelineproto

Async PHP client API for the telegram MTProto protocol.

3.4k885.1k21](/packages/danog-madelineproto)[amphp/http-server

A non-blocking HTTP application server for PHP based on Amp.

1.3k5.9M101](/packages/amphp-http-server)[amphp/http-client

An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.

7318.5M183](/packages/amphp-http-client)[craftcms/cms

Craft CMS

3.6k3.6M2.9k](/packages/craftcms-cms)[league/openapi-psr7-validator

Validate PSR-7 messages against OpenAPI (3.0.2) specifications expressed in YAML or JSON

55816.8M81](/packages/league-openapi-psr7-validator)[kelunik/acme

ACME library written in PHP.

121609.1k3](/packages/kelunik-acme)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
