Hotels want to give every guest a concierge-grade experience instant answers, effortless bookings, proactive suggestions without adding operational overhead or paying for infrastructure that sits idle between stays. At ScaleForceCloud, we delivered exactly that for a hotel client: we re-platformed an existing hotel app from traditional servers to a fully serverless architecture on AWS, and added an AI concierge on top.
The result is a guest-facing assistant that answers questions, makes bookings, and triages requests in natural language and in the guest's own language, backed by a complete platform that is secure by default, scales to zero when idle, and can be reproduced on a new AWS account by following a runbook. This post explains the business problem, the solution we built, and the architectural decisions behind it.
The business challenge
When the hotel group approached us, their guest platform a web frontend and an application backend was already live, running on traditional, always-on servers hosted at OVH. They wanted to modernize: add an AI concierge and move to an architecture that scales with demand instead of paying for capacity that sits idle between stays. Our engagement was therefore both a re-platforming and an expansion we adapted the existing frontend and backend code to run fully serverless on AWS, and built a new AI backend alongside them so the whole application became serverless and AI-enabled.
Four business requirements shaped the work:
- Elevate the guest experience. Guests should get instant, conversational help that takes action booking a table, ordering room service, reporting an issue not just a chatbot that answers FAQs.
- Keep costs proportional to usage. A hospitality platform has quiet periods. Spend should track real guest activity, not run 24/7 regardless of traffic.
- Protect guest data and isolate tenants. The platform serves multiple hotels; each hotel's data must stay strictly separated, behind an enterprise-grade security posture.
- Ship fast and repeatably. The team needed to stand up new environments quickly and move from proof of concept to production without re-architecting.
Solution overview
We built the platform as a single, coherent system on one shared Amazon VPC, composed of four layers network, AI, backend, and frontend. Everything is serverless, and Amazon CloudFront is the only component exposed to the internet; the API gateways and the database sit private or gated behind it.
We organized the codebase as four repositories, each owning one part of the system and deploying onto the same shared VPC:
| Repository | Layer | Responsibility |
|---|---|---|
| Frontend (Next.js) | Frontend | Guest-facing web app and server-side rendering |
| Backend (Symfony) | Backend | System of record: bookings, guests, catalog, loyalty |
| AI service (FastAPI) | AI | Concierge chat, request classification, recommendations, menu parsing |
| Infrastructure (Terraform) | Network + all layers | One Terraform root that provisions the shared VPC and every layer |
The core AWS building blocks are:
- AWS Lambda runs every workload the AI concierge, the backend, and the frontend rendering with no servers to manage.
- Amazon API Gateway exposes the AI and backend APIs.
- Amazon Bedrock provides the foundation model (Anthropic Claude), reached privately from inside the VPC.
- Amazon Aurora Serverless v2 is the system of record private, and able to scale to zero.
- Amazon DynamoDB, Amazon S3, Amazon SQS, Amazon EventBridge, and AWS AppSync provide caching, storage, asynchronous processing, scheduling, and realtime updates.
A guiding principle keeps four repositories manageable as one platform: the infrastructure repository owns the resource "shells," and the application repositories own the code that fills them. The two never overwrite each other, so an application deployment never disturbs the infrastructure and vice versa. The AI service is always a client of the backend it never writes to the database directly, which keeps the system of record authoritative.
Real-time guest experience: streaming responses
A concierge that makes guests wait for a full paragraph feels slow. We stream responses so text appears as it is generated the same feel as a modern AI assistant.
Delivering that on managed infrastructure took a deliberate design. A standard API Gateway integration buffers the whole response before returning it, which breaks streaming. Rather than expose a separate public endpoint, we kept streaming behind the same gateway using Amazon API Gateway response streaming: the gateway invokes the Lambda service's streaming path so it forwards data to the browser as the model produces it. Because the AWS Terraform provider did not yet expose this setting, we implemented it in a controlled, reproducible way inside our infrastructure code rather than as a manual step so every environment comes up identically.
Just as important, the AI runs inside private subnets with no public internet path and calls Amazon Bedrock over a private connection, so guest conversations and model traffic never leave the AWS network.
Right-sizing and testing the AI model
The foundation model is both the quality lever and the largest variable cost in an AI product, so we treated model selection as an engineering decision not a default. Helping customers find the right model for their use case the best balance of cost and performance is a core part of how we work at ScaleForceCloud. Amazon Bedrock makes this practical, giving access to a range of foundation models behind one API so we can evaluate options and switch models without re-architecting.
We match the model to the task. Not every job needs the most powerful model. The reasoning-heavy concierge conversation uses a strong Anthropic Claude model on Amazon Bedrock, while structured, single-shot tasks classifying a guest request, generating recommendations use a smaller, faster Claude model that costs several times less per request. Guests get top-tier quality where it matters, and the high-volume, simpler paths run at a fraction of the cost. We also cap the model's output length as a guardrail, so no single response can run away and inflate spend.
We test the model before it ships. Changing or upgrading an AI model is only safe if you can prove it still behaves. We built an automated evaluation suite that exercises the assistant against real Amazon Bedrock and the real backend, capturing its decision trajectories and flagging regressions. It runs as a gate in the deployment pipeline and again on a nightly schedule, so quality is checked continuously not just at release. This lets us adopt newer or lower-cost models as they become available with confidence, keeping the assistant both high-quality and cost-efficient over time.
Engineered infrastructure as code
We treat the entire platform as software. A single Terraform codebase describes all four layers, and a root configuration composes them as independent, reusable modules network, AI, backend, and frontend over the shared VPC. This modular design is what lets four repositories behave as one coherent platform instead of a fragile collection of scripts.
Two engineering decisions make it dependable at scale:
- Drift-free state. Terraform state is stored remotely with locking, so applies are serialized and can never be corrupted by two people at once. Crucially, every attribute a deployment pipeline manages (function code and container images) is deliberately excluded from Terraform's control, so infrastructure and application releases never fight the live platform always matches the code, with no configuration drift.
- A design that separates environments cleanly. The same modules serve every environment. A development or production environment is just a set of input values plus its own isolated state on a dedicated AWS account there is no copied, slowly diverging "prod" codebase to maintain, and work in development can never reach into production.
Provisioning the platform is genuinely complex, and we encoded that complexity so it runs identically every time. Some resources depend on others that do not yet exist container images must be in the registry before the functions that consume them, and the security perimeter needs a public URL that only exists after the edge is created. We resolved these ordering problems with a staged, phased provisioning process rather than manual intervention, which is what makes the delivery pipeline below repeatable.
Reliable, secure delivery: complex pipelines, made repeatable
We deliver the platform through automated GitHub Actions pipelines that orchestrate a deliberately non-trivial process across the four repositories: one control-plane pipeline runs Terraform, and each application repository has its own pipeline that builds an artifact and ships it into the Terraform-created shells.
The first stand-up of an environment is staged in phases to satisfy the dependency ordering: first the container images are seeded to the registry, then the core infrastructure is provisioned, then the application layer and the CloudFront edge, and finally the security gate is switched on using the now-known public URL. Each application pipeline also handles the details that make releases safe building for the correct runtime, running database migrations when needed, and verifying health after deploy. Everyday changes, by contrast, are a single pipeline run. We turned what is usually a fragile, error-prone first deployment into a documented, repeatable sequence so a new environment, or a fresh AWS account, comes up the same way every time.
A key security decision: the pipelines hold no long-lived AWS credentials. They authenticate with OpenID Connect (OIDC) federation, so AWS issues short-lived credentials only for the duration of each job. The setup has three parts:
- An IAM OIDC identity provider for GitHub's token issuer (
token.actions.githubusercontent.com, audiencests.amazonaws.com). - A single deployer IAM role that the repositories assume through
AssumeRoleWithWebIdentity; each workflow requests the token by declaringpermissions: id-token: write. - A trust policy scoped to the exact repository and branch, so only the intended branch of the intended repository can assume the role:
{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::<account-id>:oidc-provider/token.actions.githubusercontent.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" },
"StringLike": { "token.actions.githubusercontent.com:sub": "repo:<org>/<repo>:ref:refs/heads/<branch>" }
}
}
The payoff for the business is concrete: no secret keys to leak or rotate, every deployment tied to a specific repository and branch, and a full audit trail of who shipped what.
Security by design: one gated entry point
Because CloudFront is the only public door, we can enforce security in one place. Each API gateway sits behind a lightweight check that only accepts requests arriving through CloudFront, so the underlying APIs cannot be reached directly. Multi-tenant isolation is enforced in the application itself: every AI action is scoped to the guest's own hotel, so one hotel's data can never surface in another's session. The result is an enterprise-grade posture a single protected perimeter, a private database, and strict tenant separation without adding complexity for the guest.
Layered protection and observability
On top of that perimeter, we add two managed layers that a production hospitality platform needs: protection at the edge and visibility into how the system is behaving.
Protection with AWS WAF. We attach AWS WAF at two points on the AI API and on the CloudFront distribution that fronts the whole platform to filter out common web exploits and abusive traffic before it ever reaches the application. Because CloudFront is the single public door, one WAF policy protects both the frontend and the backend behind it.
Observability with Amazon CloudWatch. We instrument the platform with Amazon CloudWatch alarms on error rates and throttling, an operational dashboard, and alerts delivered through Amazon SNS so the team is notified the moment something needs attention. Logs are centralized so issues can be traced quickly.
Both layers are built into the platform as configuration switches. In lower environments they can stay off to keep things lean; in production they are turned on no code changes, just configuration. This gives the business a hardened, observable production system while keeping development environments simple and inexpensive.
Cost efficiency: a platform that scales to zero
The architecture's defining property is that it costs very little when no one is using it. Every workload is pay-per-use, and the database can pause entirely:
- Amazon Aurora Serverless v2 can scale to zero, pausing after an idle period so there is no standing database compute cost.
- AWS Lambda bills only for what runs, so the platform's many functions cost nothing when idle.
- Cold starts are handled with a lightweight scheduled warm-up instead of always-on reserved capacity, avoiding a fixed hourly charge.
- Egress and connectivity are sized for efficiency, keeping the always-on footprint small.
For the business this means spend tracks real guest activity: near-nothing during quiet periods, and scaling smoothly with demand.
One codebase, two environments: development and production
Development and production run the same infrastructure code. There is no separate "prod" project to drift out of sync an environment is simply a set of configuration values applied to the shared Terraform codebase, on its own isolated AWS account.
We keep the two accounts fully separate so that work in development can never affect live guests (blast-radius isolation), and we move between postures by changing configuration, not by re-architecting:
| Aspect | Development | Production |
|---|---|---|
| AWS account | Isolated dev account | Separate, dedicated account |
| Infrastructure code | Identical | Identical |
| AWS WAF (AI + CloudFront) | Off (lean, low-cost) | On |
| Monitoring (alarms, dashboard, alerts) | Off | On |
| Database (Aurora Serverless v2) | Scales to zero | Always-warm floor for consistent latency |
| Data | Demo/test data | Real data, no test fixtures |
| Secrets | Development values | Real secrets, managed securely |
| Egress | Cost-optimized | Option for high availability |
Because promoting to production is a configuration change rather than a rebuild, the business gets a fast, low-risk path from proof of concept to a hardened live service and standing up an entirely new environment (a second region, a new brand, a separate account) follows the same runbook.
Business outcomes
- A differentiated guest experience a real-time, action-taking AI concierge in the guest's own language.
- Costs aligned to usage a serverless, scale-to-zero design with no idle infrastructure spend, and an AI layer that uses the right-sized model for each task to control per-request cost.
- Continuously optimized, safely an automated evaluation suite against real Amazon Bedrock lets us adopt newer or lower-cost models without risking guest experience.
- Enterprise-grade security and observability a single protected entry point, AWS WAF at the edge, a private database, keyless deployments, strict multi-tenant isolation, and CloudWatch monitoring with alerts in production.
- Faster time to market one infrastructure codebase driving both development and production, so standing up a new environment or promoting to production is a configuration change and a runbook, not a rebuild.