Multitenant
This might not be as relevant for self-hosted services, but for anyone providing software as a service and offering dedicated URL paths or subdomains for individual users, after deciding whether to use subdomains (e.g. https://<user>.domain.com
) or paths (e.g. https://domain.com/<user>
), the question of how to route traffic becomes important.
The first scheme allows natural mapping to individual host machines, since on DNS the subdomain can be managed with an A
record. Handling paths, on the other hand, can be trickier. For instance, in CloudFlare, you cannot just tunnel things to a subservice — the path here just provides some sort of submapping/filtering and must be handled by the server (i.e. the server program must explicitly handle /path
).
It's said that when using ASP.NET Core, one can make use of YARP for easier reverse proxy implementation instead of rolling a custom one.
Lambda
I've had fairly smooth experience with AWS Lambda before for scheduling a Python script every 15 days — providing custom libraries is a bit tricky with .zip
upload, but otherwise the service runs happily and freely for the purpose.
Here at Methodox, we absolutely prefer everything in native C#, as the entire Divooka ecosystem is C#-native. As it turns out, shipping Lambda functions with the .NET runtime is even easier than dealing with Python — since for any "platform-dependent" C# (.NET 8) distribution, all dependencies are just regular DLL files, and uploading it as a plain .zip
is as easy as it gets.
The AWS C# templates provide a straightforward starting point but are mostly for configuring assembly-level JSON serialization rules.
using Amazon.Lambda.Core; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] public class Function { public async Task<string> FunctionHandler(ILambdaContext context) { return """ <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title></title> <link href="style.css" rel="stylesheet" /> </head> <body> <h1>Hello World!</h1> </body> </html> """; } }
Here is a function expecting a JSON payload (e.g. in POST):
using Amazon.Lambda.Core; using OpenAI.Chat; [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] public class Function { private readonly ChatClient _chatClient; public Function() { string? apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY"); if (string.IsNullOrEmpty(apiKey)) throw new InvalidOperationException("Environment variable OPENAI_API_KEY is not set."); // Initialize ChatClient for the gpt-3.5-turbo model _chatClient = new ChatClient(model: "gpt-3.5-turbo", apiKey: apiKey); } public async Task<string> FunctionHandler(Input input, ILambdaContext context) { if (input == null || string.IsNullOrEmpty(input.Prompt)) throw new ArgumentException("Input must contain a non-empty Prompt.", nameof(input)); // Call OpenAI and return the first chunk of text System.ClientModel.ClientResult<ChatCompletion> completion = await _chatClient.CompleteChatAsync(input.Prompt); return completion.Value.Content[0].Text; } } /// <summary> /// JSON input schema for the Lambda function. /// </summary> public class Input { public string Prompt { get; set; } = string.Empty; }
API Gateway
AWS offers a few similar platforms for front-facing services, and at a glance it can be a bit confusing, but it all makes a lot of sense when understood properly:
- Lambda is where the runtime is hosted and where things actually get executed.
- API Gateway comes with handy path configuration and response header overrides, and is used to aggregate/consume different services and expose them as structured endpoints.
- CloudFront is for CDN and supposedly provides better caching, though I'm not super clear on its features/architecture yet.
With these technologies, everything is supposed to be API-controllable, with no need for a single local server or explicit proxy handling — just do some configuration in the console.
Conclusion
I think this is as big a discovery as CloudFlare tunneling, and it immediately opens new doors. This setup should provide enough infrastructure for a barebone multitenant service.
What's more, the free-tier nature of many AWS services — including Lambda, API Gateway, DynamoDB, and CloudFront — enables some very creative combinations when it comes to service/endpoint distributions, especially during development or for distributed purposes at any scale.
Summary of new capabilities we've discovered over the past few weeks:
- CloudFlare for tunneling: allows local dev server deployment.
- AWS Lambda: serverless workloads with dynamic responses. Use for websites and APIs.
- API Gateway: effectively enables multitenant setup.
Top comments (0)