Communication Within the Same Environment
Overview
Use BindableEvent or BindableFunction to communicate between scripts that live in the same environment, such as between servers or between clients.
Use BindableEvent when you only need to send a notification and move on, and BindableFunction when you need the result of the work sent back to you.
Neither object can cross the client-server boundary. For communication that crosses it, use RemoteEvent or RemoteFunction.
BindableEvent and BindableFunction Objects
BindableEvent is an object provided to handle events within the same environment, supporting one-way communication. The sending script keeps running without stopping.
BindableFunction is an object provided to handle requests and responses within the same environment, supporting two-way communication. The calling script yields until the assigned callback returns a value.

Direction
One-way (notification)
Two-way (request and response)
Sender behavior
Keeps running without stopping
Waits until a value is returned
How to connect
Event:Connect(function) — many can be connected
OnInvoke = function — only one can be assigned
Return value
Cannot receive one
Receives multiple values as a Tuple
Error on the receiving side
Does not affect other connected functions
Propagates to the caller
Use BindableEvent for notifications that need no result. A synchronous call stops the caller, so a long-running task also delays the rest of the game flow.
💡 Tip. To clearly distinguish whether the communication is between Server to Server or Client to Client, it is recommended to use prefixes such as S2S_ or C2C_ in the name. This makes the object’s role intuitive and improves code readability and maintainability.

Implementing Communication with BindableEvent
When firing an event with BindableEvent, you can send arguments along with it. These arguments are passed when calling the Fire method and can be received by the callback function on the receiving side.
Server ➡ Server
In Script1
In Script2
Client ➡ Client
In LocalScript1
In LocalScript2
Implementing Communication with BindableFunction
The handling script assigns a callback to OnInvoke, and the calling script calls it with the Invoke method. Arguments passed to Invoke arrive at the callback as-is, and whatever the callback returns goes back to the caller.
Server ➡ Server
In Script1 (handling side)
In Script2 (calling side)
Client ➡ Client
In LocalScript1 (handling side)
In LocalScript2 (calling side)
Callback Rules for OnInvoke
OnInvoke is not an event but a property that holds a function. It works differently from Event, so keep these three points in mind.
You cannot use
:Connect(). Assign it asOnInvoke = function.Only one function is kept. If you assign more than once, only the last assigned function runs.
If you omit
return, the caller receivesnil. Using that value directly can cause an error later in the code.
Overlapping calls each run the callback separately. If you replace OnInvoke while a call is in progress, that call finishes with the previous function, and only new calls made afterward use the new one.
Important Notes
The Call Never Resumes Without a Callback
If you call a BindableFunction whose OnInvoke has not been assigned, the calling thread stops forever with no error and no timeout. There is no way to cancel the wait.
Design your initialization order so the callback is assigned before any call is made.
If the work can take a long time, consider sending the request with a BindableEvent and reporting the result through a separate event when it finishes.
You can tell a hang and an error apart by the symptom. Assigning a value that is not a function (a module table, for example) to OnInvoke passes silently, and the error appears the moment you call it. In other words, if nothing happens at all, the callback is not assigned; if an error appears right at the call, a non-function value was assigned.
BindableEvent has no such hang. Even with no connected function, the script that called Fire keeps running.
Callback Errors Propagate to the Caller
An error raised in a BindableFunction callback is delivered to the caller and interrupts the calling code. If the work can fail, wrap the call in pcall() or return a success flag instead of raising an error.
BindableEvent runs each connected function on its own thread, so an error in one of them affects neither the others nor the sender.
Table Arguments Are Copies
Both objects copy the table you pass before handing it to the receiving side. Filling an argument table on the receiving side leaves the sender’s original empty, so you must receive what you need as a return value. Metatables are not delivered, so you cannot pass an object with methods as-is.
When passing a table, use string keys only. If a table holds both array elements and named fields, the named fields disappear, and instances or functions used as keys turn into strings that can no longer be looked up with the original key. No error or warning is raised during this process.
Advanced Usage
For communication that needs no return value, use BindableEvent so the caller does not stop.
If you only need to share values or functions, a ModuleScript is simpler and faster. Use the Bindable objects when you need to keep scripts loosely coupled.
Do not perform long waits inside a callback (
task.wait, external communication, and so on). The caller waits just as long.When using a single object to handle several kinds of requests, add a first argument that indicates the request type.
Clients of different players cannot communicate through these objects. In that case, use RemoteEvent or RemoteFunction, which go through the server.
Last updated