Skip to content

Kévin Dunglas

Founder of Les-Tilleuls.coop (worker-owned cooperative). Creator of API Platform, FrankenPHP, Mercure.rocks, Vulcain.rocks and of some Symfony components.

Menu
  • Talks
  • Resume
  • Sponsor me
  • Contact
Menu
10 years of API Platform

The Best of Both Worlds: Go-Powered gRPC for Your PHP and API Platform Apps

Posted on September 19, 2025September 19, 2025 by Kévin Dunglas

I’m thrilled to announce a brand-new feature I unveiled today during my opening keynote at the API Platform Conference: an experimental extension for FrankenPHP that brings gRPC support to PHP! 🚀

This extension allows you to build high-performance gRPC servers using PHP, Go, or even a mix of both. It leverages the power of FrankenPHP’s Go extension support and the mature gRPC-Go library to deliver exceptional performance.

Ready to dive into the code? The brand-new gRPC extension is free and open-source and waiting for you on GitHub! If you’re as excited about bringing high-performance gRPC to PHP as I am, head over to the repository and give it a star ⭐. Your support is hugely appreciated and helps the project grow!

Key Features of the gRPC Extension

  • High-Performance Server: Run a powerful gRPC server with FrankenPHP, executing your PHP code in a persistent worker loop for maximum efficiency.
  • PHP and Go Handlers: Write your gRPC service handlers in either PHP or Go, giving you the flexibility to use the best language for the job. You can even mix and match them within the same server!
  • Full gRPC-Go Compatibility: Benefit from all the features of the robust and widely-used gRPC-Go library.
  • Pure Go Implementation: The extension is written entirely in Go, with no C code involved.
  • East API Platform Integration: Seamlessly integrate with API Platform for building powerful and modern APIs.

This extension is highly experimental and not yet recommended for production use. It currently requires the main branch of FrankenPHP and its public API may change at any time without notice.

Getting Started

Let’s walk through how to set up a gRPC server with the new FrankenPHP extension.

1. Create a New Go Module for Your gRPC Server

go mod init example.com/mygrpcserver 

2. Create a Protobuf Definition

First, define your gRPC service and messages in a .proto file. Here’s a simple example:

syntax = "proto3";

option go_package = "example.com/mygrpcserver/helloworld";

package helloworld;

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

Then, generate the Go code from your .proto file:

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld/helloworld.proto

3. Implement the gRPC Server in Go

Next, create the Go part of your gRPC server. This code will handle the gRPC requests and forward them to your PHP worker.

package mygrpcserver

import (
    "context"
    "fmt"

    pb "example.com/mygrpcserver/helloworld"
    "github.com/dunglas/frankenphp"
    phpGrpc "github.com/dunglas/frankenphp-grpc"
    "github.com/go-viper/mapstructure/v2"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

func init() {
    phpGrpc.RegisterGrpcServerFactory(func() *grpc.Server {
        s := grpc.NewServer()
        pb.RegisterGreeterServer(s, &server{})
        reflection.Register(s)

        return s
    })
}

type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    if in.Name == "" {
        return nil, fmt.Errorf("the Name field is required")
    }

    // Convert the request to a map[string]any
    var phpRequest map[string]any
    if err := mapstructure.Decode(in, &phpRequest); err != nil {
        return nil, err
    }

    // Call the PHP code, pass the map as a PHP associative array
    phpResponse := phpGrpc.HandleRequest(phpRequest)

    // Convert the PHP response (a map) back to a HelloReply struct
    var response pb.HelloReply
    if err := mapstructure.Decode(phpResponse.(frankenphp.AssociativeArray).Map, &response); err != nil {
        return nil, err
    }

    return &response, nil
}

4. Implement the gRPC Service Handler in PHP

Now, create a grpc-worker.php file to handle the logic of your gRPC service.

<?php

// Require the Composer autoloader here if needed (API Platform, Symfony, etc.)
//require __DIR__ . '/vendor/autoload.php';

// Handler outside the loop for better performance (doing less work)
$handler = static function (array $request): array {
    // Do something with the gRPC request

    return ['message' => "Hello, {$request['Name']}"];
};

$maxRequests = (int)($_SERVER['MAX_REQUESTS'] ?? 0);
for ($nbRequests = 0; !$maxRequests || $nbRequests < $maxRequests; ++$nbRequests) {
    $keepRunning = \frankenphp_handle_request($handler);

    // Call the garbage collector to reduce the chances of it being triggered in the middle of the handling of a request
    gc_collect_cycles();

    if (!$keepRunning) {
        break;
    }
}

5. Enable the FrankenPHP Extension with a Caddyfile

Create a Caddyfile to configure FrankenPHP and enable the gRPC extension.

{
    frankenphp
    grpc {
        address :50051
        worker grpc-worker.php
        min_threads 50
    }
}

6. Build and Run

Finally, build your custom FrankenPHP binary with the gRPC extension and run it.

Be sure to install FrankenPHP dependencies first.

XCADDY_DEBUG=1 \
    CGO_ENABLED=1 \
    XCADDY_GO_BUILD_FLAGS="-tags=nobadger,nomysql,nopgx" \
    CGO_CFLAGS="$(php-config --includes) -I/opt/homebrew/include/" \
    CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs) -L/opt/homebrew/lib/ -L/usr/lib" \
    xcaddy build

./caddy run

Your gRPC server will now be running on localhost:50051. I recommend using a tool like gRPC UI to test your new server.

I’m excited to see what the community builds with this new capability. Your feedback is highly welcome, so please give it a try and share your thoughts!

Here are the slides I presented during the keynote:

Related posts:

  1. PHP and Symfony Apps As Standalone Binaries
  2. The PHP Revolution Is Underway: FrankenPHP 1.0 Beta
  3. API Platform 2.1 Feature Walkthrough: Create Blazing Fast Hypermedia APIs, Generate JS Apps
  4. FrankenPHP has reached 10,000 stars: the elePHPant plush toy is coming!

Leave a ReplyCancel reply

Social

  • Bluesky
  • GitHub
  • LinkedIn
  • Mastodon
  • X
  • YouTube

Links

  • API Platform
  • FrankenPHP
  • Les-Tilleuls.coop
  • Mercure.rocks
  • Vulcain.rocks

Subscribe to this blog

Top Posts & Pages

  • The Best of Both Worlds: Go-Powered gRPC for Your PHP and API Platform Apps
  • Unleash the Monster: The FrankenPHP elePHPant is Born
  • FrankenPHP has reached 10,000 stars: the elePHPant plush toy is coming!
  • PHP and Symfony Apps As Standalone Binaries
  • Symfony's New Native Docker Support (Symfony World)
  • JSON Columns and Doctrine DBAL 3 Upgrade
  • FrankenPHP: The Modern Php App Server, written in Go
  • FrankenPHP’s New Features: Thread Autoscaling, Mostly Static Binaries, deb and RPM Packages, Caddy 2.10…
  • FrankenPHP 1.3: Massive Performance Improvements, Watcher Mode, Dedicated Prometheus Metrics, and More
  • How to debug Xdebug... or any other weird bug in PHP

Tags

Apache API API Platform Buzz Caddy Docker Doctrine FrankenPHP Go Google GraphQL HTTP/2 Hydra hypermedia Hébergement Javascript JSON-LD Kubernetes La Coopérative des Tilleuls Les-Tilleuls.coop Lille Linux Mac Mercure Mercure.rocks Messagerie Instantanée MySQL performance PHP Punk Rock Python React REST Rock'n'Roll Schema.org Security SEO SEO Symfony Symfony Live Sécurité Ubuntu Web 2.0 webperf XML

Archives

Categories

  • DevOps (85)
    • Ubuntu (68)
  • Go (20)
  • JavaScript (46)
  • Mercure (7)
  • Opinions (91)
  • PHP (175)
    • API Platform (79)
    • FrankenPHP (14)
    • Laravel (1)
    • Symfony (97)
    • Wordpress (6)
  • Python (14)
  • Security (15)
  • SEO (25)
  • Talks (46)
© 2025 Kévin Dunglas | Powered by Minimalist Blog WordPress Theme