Data Proxy and Translation Services
Flyte uses the Data Proxy and Translator services to offload data-heavy operations from the central control plane. By handling large literal translations and providing direct access to object storage via signed URLs, these services prevent large data payloads from causing congestion in the core workflow engine.
Translating Literals for the UI
The TranslatorService (defined in dataproxy/translator.go) is responsible for converting between Flyte's internal protobuf-based Literal format and the JSON format used by the Flyte UI (Launch Forms).
Converting Inline Literals
When you need to display a launch form for a task or workflow, the UI calls LiteralsToLaunchFormJson. This method takes a map of literals and their corresponding variable definitions to produce a JSON schema.
// Example from dataproxy/translator_test.go
svc := NewTranslatorService(nil, nil)
resp, err := svc.LiteralsToLaunchFormJson(context.Background(), connect.NewRequest(&workflow.LiteralsToLaunchFormJsonRequest{
Literals: testNamedLiterals(), // Map of Flyte Literals
Variables: testVariableMap(), // Variable definitions (types)
}))
Handling Offloaded Literals
For large inputs or outputs that are already stored in object storage (S3/GCS), the service can read them directly using a LiteralsUri. To ensure security, this requires an ActionId.
Internally, readOffloadedLiterals verifies the request by calling the RunService:
- It fetches authorized data URIs for the specific
ActionIdvias.runClient.GetActionDataURIs. - It validates that the requested
LiteralsUrimatches either theInputsUriorOutputsUrireported by theRunService. - It reads the protobuf data directly from storage using the
dataStore.
This mechanism ensures that the Data Proxy only translates data that the user is authorized to access for a specific execution.
Direct Storage Access via Signed URLs
The Service in dataproxy/service/dataproxy_service.go provides a way for clients (like Flytekit or the UI) to interact directly with object storage without streaming data through the Flyte backend.
Requesting Upload Locations
To upload data, you call CreateUploadLocation. The service returns a signed URL that allows a direct PUT request to the storage provider.
req := &connect.Request[dataproxy.CreateUploadLocationRequest]{
Msg: &dataproxy.CreateUploadLocationRequest{
Project: "my-project",
Domain: "development",
Filename: "data.parquet",
FilenameRoot: "unique-execution-id",
ContentMd5: []byte("..."), // Optional but recommended
ExpiresIn: durationpb.New(30 * time.Minute),
},
}
resp, err := service.CreateUploadLocation(ctx, req)
// resp.Msg.SignedUrl is the URL for the client to use
The service constructs the storage path using the pattern:
{storage_prefix}/{project}/{domain}/{filename_root}/{filename}
If FilenameRoot is not provided, it uses a URL-safe base32 encoding of the ContentMd5 hash as the directory name.
Safety and Overwrite Protection
The Data Proxy performs a best-effort check to prevent accidental overwrites in checkFileExists. If a file already exists at the target location:
- If no
ContentMd5was provided in the request, it rejects the upload withCodeAlreadyExists. - If a
ContentMd5was provided, it compares it against the existing file's metadata. It only allows the upload if the hashes match (effectively making the operation idempotent).
Input Management and Caching
The UploadInputs method is a specialized utility for persisting task inputs to storage in a way that supports Flyte's caching mechanism.
Deterministic Hashing
When you call UploadInputs, the service:
- Resolves the task template to identify variables marked in
cache_ignore_input_vars. - Filters out these ignored variables using
filterInputs. - Computes a deterministic FNV-64a hash of the remaining inputs using
hashInputsProto.
This hash is used as part of the storage path:
{storage_prefix}/{org}/{project}/{domain}/offloaded-inputs/{hash}/inputs.pb
By using a deterministic hash of the non-ignored inputs, Flyte ensures that identical input sets result in the same storage location, facilitating cache hits across different executions.
Configuration
The behavior of these services is controlled via the DataProxyConfig (in dataproxy/config/config.go). Key configuration options include:
- Upload Limits:
MaxSize(default 100Mi) restricts the size of data that can be uploaded. - Expiration:
MaxExpiresIn(default 1h) sets the upper bound for how long signed URLs remain valid. - Storage Prefix:
StoragePrefix(default "uploads") defines the root directory in the object store where the Data Proxy manages files.
These settings are registered under the dataproxy configuration section and can be adjusted to match the storage policies of your Flyte deployment.