Carlos Gude Sánchez

Carlos Gude Sánchez

Senior Backend Engineer & Software Architect

PHP · Symfony · Legacy Modernisation · API Integrations · DDD / Hexagonal

Location
Cambados (Pontevedra), Spain · CET
Availability
Open to fully remote roles
Email
carlos.sgude@gmail.com
GitHub
CarlosGude (opens in a new tab)
LinkedIn
carlos-gude (opens in a new tab)

The same data as a readable CV or as the JSON file this page is built from. Open cv.en.json

Profile

Senior Backend Engineer and Software Architect with 10+ years building and modernising PHP/Symfony systems, including high-volume distributed platforms. Specialised in migrating critical legacy systems with zero downtime, making change safe through tests and static analysis gated in CI, and designing integration layers for external APIs. Production experience in logistics, travel, public transport and retail SaaS; author of the open-source IntegrationEngine bundle.

Experience

  1. – Datcisions Senior Backend Engineer Retail SaaS

    Stock and purchase-planning SaaS for fashion and retail brands. Fixed-term engagement focused on platform quality and modularisation.

    • Raised PHPStan on the core platform from level 5 to 9 and cut the level-9 baseline from 3,339 to 239 errors (−93%).
    • Recovered a test suite that no longer ran and grew it to 2,100+ passing tests.
    • Modularised the monorepo into Symfony bundles: extracted IAM and access control from Security, split 127 migrations across modules and removed 53,000 lines of dead code in the process.
    • Built the Holded cloud ERP connector from scratch and shipped it to production in 11 days, with PHPStan and PHP-CS-Fixer gated in CI.
    • Found and fixed two IDOR vulnerabilities during a self-initiated security review.
  2. – PrimeIT Senior Backend Engineer IT consultancy

    International IT consultancy.

    • Led the zero-downtime migration of a legacy system with 100+ endpoints from PHP 7.4 / Symfony 4 to PHP 8.3 / Symfony 6, using AI coding agents for mechanical refactors with every change gated by tests and static analysis.
    • Rewrote authentication using Symfony’s native Security Component, eliminating vulnerabilities in the previous model.
  3. – Quadrant TravelTech Backend Engineer, Integrations Travel

    Via Interacso from May 2023 to Jan 2024, then hired directly by Quadrant.

    • Designed and implemented 5+ travel integrations, including Booking.com, Iberia, Lleego and Hostalia.
    • Built a multi-provider integration layer where new providers could be added without changing the core.
  4. – Auro Backend Engineer Logistics

    Last-mile logistics platform.

    • Developed and integrated 10+ external partner APIs for a last-mile logistics platform with real-time shipment tracking.
    • Designed the event and messaging layer coordinating multiple carriers, handling 300,000+ messages per minute for rider positioning under high concurrency (RabbitMQ, SQS and Symfony Messenger, with idempotent consumers).
  5. – Jamenet Backend Engineer, project-based Public transport

    Metro Bilbao.

    • Built the Drupal–Symfony–Vue integration for Metro Bilbao, a 24/7 system serving real passenger traffic.
    • Implemented real-time bulk processing of route and timetable data.

Earlier experience

  1. –

    Freelance · Real-time streaming platform

    Solo end-to-end build of a Twitch-style platform: live chat over WebSockets, WebRTC video streaming, payments with Stripe, PayPal and Redsys, a virtual economy and moderation.

  2. –

    Syntelix · Backend Engineer

    Real-time ingestion pipelines and ordered, lossless messaging for maritime telemetry.

  3. –

    Card2Card · Full-stack Symfony Developer

    Sole technical owner of a customisable SaaS e-commerce platform.

  4. –

    Freelance · Web and PHP backend development

    10+ projects for local SMEs, agencies, e-commerce and hospitality/tourism clients.

Skills, languages & education

Technical skills

  • Architecture

    Hexagonal · DDD · Clean Architecture · Event-Driven · CQRS

  • Backend

    PHP 8.x · Symfony 6 / 7 / 8 · API Platform · Doctrine · REST · Webhooks

  • Quality

    TDD · PHPUnit · PHPStan · Infection · Deptrac · PHP-CS-Fixer · SonarQube

  • Infrastructure

    RabbitMQ · SQS · Docker · CI/CD with GitHub Actions · Linux

  • Databases

    MySQL · PostgreSQL · Redis

  • AI-assisted development

    AI coding agents for refactors, test generation, migrations, code review and documentation, with every change gated by PHPStan max, Deptrac, mutation testing and human code review

Languages

Spanish
Native
English
Professional working proficiency

Education

Higher Technician in Network Computer Systems Administration –
EQF level 5
Self-taught
PHP, Symfony and software architecture, learned independently. Ongoing self-directed study in architecture, DDD and the PHP/Symfony ecosystem, applied in professional and open-source work.

Projects

IntegrationEngine

Open-source Symfony bundle · Author & maintainer

A common structure for building and maintaining external API integrations in Symfony.

Requires
PHP 8.2+ · Symfony 6.4 / 7 / 8
Licence
MIT
  1. Action + Context
  2. IntegrationEngine
  3. External API
  4. Mapper
  5. Typed Response
Why I built it

Every time I integrated an external API into Symfony, I ended up solving similar pieces again: authentication, HTTP requests, response mapping and error handling. And each integration tended to grow its own conventions. IntegrationEngine came out of that experience.

How it is organised
  • Each operation against the external API is an Action.
  • A Mapper turns the external response into a typed Response object.
  • The bundle handles the shared flow: configuration, authentication and HTTP transport.
  • Each integration keeps the provider-specific details where they belong.

A repeatable way of working — clear contracts and a consistent structure — based on problems I have met in production. Providers still differ; the bundle gives those differences a predictable place to live.

Real example: Fetching a movie from TMDB Taken from the demo application
  1. Declare the operation

    Method, path and mapper for the get_movie action.

    src/Integrations/Tmdb/Tmdb.yaml
    get_movie:
      action: 'App\Integrations\Tmdb\GetMovie\GetMovieAction'
      method: GET
      path: /3/movie/{movie_id}
      mapper: 'App\Integrations\Tmdb\Mappers\GetMovieMapper'
  2. Call it from the application

    A small facade keeps the engine out of controllers and services.

    src/Integrations/Tmdb/TmdbIntegration.php
    public function getMovie(int $movieId): GetMovieResponse
    {
        $engine = $this->registry->get('tmdb');
        $context = DefaultActionContext::create(['movie_id' => $movieId]);
    
        $response = $engine->send('get_movie', $context);
        \assert($response instanceof GetMovieResponse);
    
        return $response;
    }
  3. TMDB answers with its own model

    The test fixture the demo uses for this call: 25 fields, most of which the application does not need.

    tests/Catalog/Infrastructure/Integrations/Tmdb/Fixtures/get-movie.json
    {
      "adult": false,
      "backdrop_path": "/fhvyh6G8M55gkTIPCbeFjvyAh4c.jpg",
      "belongs_to_collection": null,
      "budget": 250000000,
      "genres": [
        {
          "id": 28,
          "name": "Action"
        },
        {
          "id": 12,
          "name": "Adventure"
        }
      ],
      "homepage": "https://www.marvel.com/movies/avengers-endgame",
      "id": 299536,
      "imdb_id": "tt4154796",
      "original_language": "en",
      "original_title": "Avengers: Endgame",
      "overview": "After the devastating events that decimated the planet and wiped out half of all life, the Avengers assemble once more in order to reverse Thanos' actions and restore balance to the universe.",
      "popularity": 408.72,
      "poster_path": "/or06FN4Hf2tfsWASP2Oa6aSy0l1.jpg",
      "production_companies": [
        {
          "id": 420,
          "logo_path": "/hUzeosd33nzE5MCNsZxCGEKTW5l.png",
          "name": "Marvel Studios",
          "origin_country": "US"
        }
      ],
      "production_countries": [
        {
          "iso_3166_1": "US",
          "name": "United States of America"
        }
      ],
      "release_date": "2019-04-26",
      "revenue": 2798200000,
      "runtime": 181,
      "spoken_languages": [
        {
          "english_name": "English",
          "iso_639_1": "en",
          "name": "English"
        }
      ],
      "status": "Released",
      "tagline": "Part of the journey is the end.",
      "title": "Avengers: Endgame",
      "video": false,
      "vote_average": 8.3,
      "vote_count": 32000
    }
  4. The Mapper keeps what the application uses

    Provider field names stay here; the rest of the code only sees the typed response.

    src/Integrations/Tmdb/Mappers/GetMovieMapper.php
    protected static function transform(AbstractAction $action, array $response, array $headers): ResponseInterface
    {
        /** @var array{id: int, title: string, overview: string, poster_path: string, vote_average: float, release_date: string} $response */
        return new GetMovieResponse(
            id: $response['id'],
            title: $response['title'],
            overview: $response['overview'],
            posterPath: $response['poster_path'],
            voteAverage: $response['vote_average'],
            releaseDate: $response['release_date'],
        );
    }
  5. Typed response

    GetMovieResponse::toArray() for the fixture above.

    GetMovieResponse
    {
      "id": 299536,
      "title": "Avengers: Endgame",
      "overview": "After the devastating events that decimated the planet and wiped out half of all life, the Avengers assemble once more in order to reverse Thanos' actions and restore balance to the universe.",
      "poster_path": "/or06FN4Hf2tfsWASP2Oa6aSy0l1.jpg",
      "vote_average": 8.3,
      "release_date": "2019-04-26"
    }

Source: integrationEngine-demo/tree/main/src/Integrations/Tmdb (opens in a new tab)

IntegrationEngine Demo

Symfony application · Author

Executable reference application that uses the bundle against real APIs, including concurrent requests with a measured 5–13× speedup over sequential calls.

Requires
PHP 8.4+ · Symfony 7.4
Licence
MIT
What it covers
  • REST · TMDB
  • GraphQL · Countries
  • CSV · Supplier
  • Stripe form-encoded requests and signed webhooks
Implementation notes
  • Concurrent sendMany() workloads with partial failure isolation; measured 5–13× speedup for 20 concurrent movie loads over sequential execution.
  • Bounded contexts and gateways isolate integrations from business code.
  • CI enforces tests, PHPStan max, PHP-CS-Fixer, Deptrac, production install / Docker validation and mutation testing.

Contact

Open to fully remote Senior Backend Engineer and Software Architect roles.