On this page
TransferGo
Founded in 2012, TransferGo provides international money transfer services with a focus on accessibility, speed, and affordability for migrants. The company operates in over 160 countries and serves millions of customers globally, ensuring fast and reliable cross-border payments.
tl;dr just go and have a look atfull production-used AsyncAPI document
Challenges
In 2021, TransferGo's Backend Guild identified challenges with documenting both REST and asynchronous APIs. Different teams used varying approaches, which created inconsistencies and difficulties in maintaining up-to-date API schemas. As services grew past 50 and more events were introduced, inconsistencies and invalid schemas emerged. Additionally, YAML-based documentation was not user-friendly, making discoverability and adoption harder. With over 300 channels, visibility into published events and ensuring trust across distributed systems became a significant challenge.
Solution
TransferGo adopted the AsyncAPI specification to unify documentation practices and improve developer experience. Instead of an API-first approach, they introduced a code-first documentation model using an internal library. This library leverages Reflection in PHP and .NET to generate AsyncAPI schemas directly from DTOs, reducing duplication and ensuring consistency.
To maintain schema quality, TransferGo integrated AsyncAPI CLI into their pipelines, automating validation and optimization of large schemas. They also contributed to schema scoring capabilities in AsyncAPI CLI, encouraging teams to keep docs clean and consistent.
For accessibility, TransferGo automated publishing of AsyncAPI definitions using GitHub Actions. Schemas are stored in S3 and surfaced through Port.io Developer Portal, providing a single interface for developers to browse, search, and visualize service contracts.
At scale, TransferGo introduced Event Catalog to map their 300+ channels and highlight integration gaps. For testing, they adopted contract testing with Microcks and LocalStack, integrated into Jenkins CI, enabling validation of service interactions against AsyncAPI definitions. Finally, their internal CLI tool, API Guardian, helps ensure schema coverage by comparing AsyncAPI definitions with deployed infrastructure.
Use Case
TransferGo uses AsyncAPI to unify async API documentation across services, generate schemas from code via internal libraries, validate and optimize schemas in CI pipelines, publish schemas to Port.io Developer Portal for centralized access, build an Event Catalog for visibility into 300+ channels, and support contract testing with Microcks.
More Details
Testing strategy
Contract testing with Microcks and LocalStack integrated into Jenkins CI, validating message-driven services without requiring cloud infrastructure.
Approach to code generation
Code-first generation of AsyncAPI schemas is achieved via internal libraries in PHP and .NET. These libraries automatically reflect DTOs into message payload definitions, ensuring up-to-date and consistent documentation across services.
Architecture
TransferGo relies heavily on an Event Driven Architecture, ensuring instant money transfers and reliable asynchronous communication. Services publish and consume events primarily through AWS Simple Notification Service (SNS) and Simple Queue Service (SQS), with Kafka used where applicable. Symfony-based workers handle incoming messages, while validation and coverage tools ensure contracts remain trustworthy.
More Details about AsyncAPI
How AsyncAPI documents are stored
Schemas are stored in GitHub repositories and automatically published to an S3 bucket. Port.io Developer Portal ingests these schemas to make them accessible to developers.
Where maintainers edit AsyncAPI documents
Documentation is maintained via code-first libraries. GitHub Actions pipelines validate and publish updates automatically. AsyncAPI CLI is used for validation, optimization, and schema scoring.
What extensions are used
None
How documentation is generated
AsyncAPI React component was initially used for rendering. Today, Port.io Developer Portal serves as the central platform, presenting all AsyncAPI schemas in a unified, visual interface.
What bindings are used
None
What tools are used
TransferGo relies on AsyncAPI CLI, AsyncAPI React, AsyncAPI Modelina, Port.io Developer Portal, Event Catalog, Microcks, LocalStack, and API Guardian (internal CLI).
Schemas
Storage strategy
Schemas are generated from service code and stored in GitHub repositories, with automated publishing to an S3 bucket for central access.
Schema Registry
None, schemas are distributed via S3 and Port.io Developer Portal.
Versioning of schemas
Versioning is handled per repository and service team, aligned with service releases.
Validation of message schemas
AsyncAPI CLI is used to validate schemas for correctness and optimize file sizes. Jenkins CI pipelines enforce schema validation during builds.
Additional Resources
See slides from 2023 that show early days of adoption
Production-use AsyncAPI document
1asyncapi: 3.0.0
2info:
3 title: Remittance Service Event Bus Example
4 version: 1.0.0
5 description: |
6 Example AsyncAPI 2.6.0 model for a Remittance Service.
7 A user makes a cross-border transaction request.
8 Events are published to AWS SNS, which pushes them to an SQS queue.
9 Downstream services consume the event from SQS.
10servers:
11 aws:
12 host: '{service}.{region}.amazonaws.com'
13 protocol: https
14 description: AWS endpoints for SNS and SQS.
15 variables:
16 service:
17 enum:
18 - sns
19 - sqs
20 default: sns
21 region:
22 default: us-east-1
23 description: AWS region used for the SNS/SQS resources.
24channels:
25 remittance-transactions-topic:
26 address: sns/remittance-transactions-topic
27 messages:
28 publishRemittanceTransactionToSNS:
29 $ref: '#/components/messages/RemittanceTransactionRequested'
30 description: SNS topic for remittance transaction events.
31 remittance-transactions-queue:
32 address: sqs/remittance-transactions-queue
33 messages:
34 consumeRemittanceTransactionFromSQS:
35 $ref: '#/components/messages/RemittanceTransactionRequested'
36 description: SQS queue that receives messages forwarded from SNS topic via
37 subscription.
38operations:
39 publishRemittanceTransactionToSNS:
40 action: receive
41 channel:
42 $ref: '#/channels/remittance-transactions-topic'
43 summary: Publish RemittanceTransactionRequested event to SNS topic
44 messages:
45 - $ref: '#/channels/remittance-transactions-topic/messages/publishRemittanceTransactionToSNS'
46 consumeRemittanceTransactionFromSQS:
47 action: send
48 channel:
49 $ref: '#/channels/remittance-transactions-queue'
50 summary: >-
51 Consumer service polls SQS to consume RemittanceTransactionRequested
52 events.
53 messages:
54 - $ref: '#/channels/remittance-transactions-queue/messages/consumeRemittanceTransactionFromSQS'
55components:
56 messages:
57 RemittanceTransactionRequested:
58 name: RemittanceTransactionRequested
59 title: Remittance Transaction Requested
60 summary: Event emitted when a user requests to send money cross-border.
61 contentType: application/json
62 payload:
63 type: object
64 required:
65 - transactionId
66 - transactionType
67 - createdAt
68 - sender
69 - receiver
70 - amount
71 - currency
72 - paymentMethod
73 properties:
74 transactionId:
75 type: string
76 format: uuid
77 description: Unique transaction identifier.
78 transactionType:
79 type: string
80 description: Type of transaction.
81 createdAt:
82 type: string
83 format: date-time
84 description: ISO8601 timestamp for when the request was made.
85 sender:
86 type: object
87 required:
88 - name
89 - email
90 - country
91 properties:
92 name:
93 type: string
94 email:
95 type: string
96 format: email
97 country:
98 type: string
99 description: ISO 3166-1 alpha-2 country code
100 receiver:
101 type: object
102 required:
103 - name
104 - email
105 - country
106 properties:
107 name:
108 type: string
109 email:
110 type: string
111 format: email
112 country:
113 type: string
114 description: ISO 3166-1 alpha-2 country code
115 amount:
116 type: number
117 format: double
118 description: Amount requested to transfer.
119 currency:
120 type: string
121 description: ISO 4217 currency code.
122 paymentMethod:
123 type: string
124 description: Payment method used to fund the transaction.
125 enum:
126 - card
127 - wire_transfer
128 - bank_account
129 examples:
130 - name: remittance.transaction.requested.example
131 summary: Example remittance transaction request
132 payload:
133 transactionId: 33333333-3333-3333-3333-333333333333
134 transactionType: remittance.requested
135 createdAt: '2025-09-16T10:15:00Z'
136 sender:
137 name: Jonas Petrauskas
138 email: jonas.petrauskas@example.lt
139 country: LT
140 receiver:
141 name: Olena Shevchenko
142 email: olena.shevchenko@example.ua
143 country: UA
144 amount: 750
145 currency: EUR
146 paymentMethod: wire_transfer