Tech Assessment: Church Member & Service Management System
Target organisation: The Church of Jesus Christ of Latter-day Saints (LDS Church). This document describes a serverless, cost-efficient solution using AWS services and the AWS SDK for Java.
Objective
Design and implement a serverless system to manage members and service activities for a local church unit. The solution must be secure, scalable, reproducible via Infrastructure-as-Code, and cost-aware. It demonstrates practical use of AWS SDK for Java, Lambda, API Gateway, Aurora Serverless v2, S3, and CloudFormation.
Detailed Requirements
- Provide REST APIs for members and service activities (CRUD operations).
- Support attachments (images, PDFs) stored in S3.
- Persist relational data in Aurora Serverless v2 (MySQL) via Data API.
- Deploy infrastructure using CloudFormation templates.
- Monitor costs with AWS Budgets and logs via CloudWatch.
Entities & Fields
- Member
-
Fields:
- member_id (UUID, PK)
- first_name (String)
- last_name (String)
- date_of_birth (Date)
- email (String)
- phone_number (String)
- ward (String)
- calling (String, optional)
- created_at, updated_at (Timestamps)
- ServiceActivity
-
Fields:
- activity_id (UUID, PK)
- name (String)
- description (String, optional)
- date (Date)
- location (String, optional)
- leader_id (UUID, FK → Member.member_id)
- created_at, updated_at (Timestamps)
- ActivityParticipant
-
Fields:
- participant_id (UUID, PK)
- activity_id (UUID, FK → ServiceActivity.activity_id)
- member_id (UUID, FK → Member.member_id)
- role (String, optional)
- Attachment
-
Fields:
- attachment_id (UUID, PK)
- owner_type (Enum: MEMBER or ACTIVITY)
- owner_id (UUID)
- filename (String)
- s3_key (String)
- uploaded_at (Timestamp)
Relationships
- Member → ServiceActivity: 1-to-many (a member can lead many activities)
- ServiceActivity ↔ ActivityParticipant ↔ Member: many-to-many (members participate in activities)
- Member or ServiceActivity ↔ Attachment: 1-to-many
AWS Architecture Overview
- AWS Lambda (Java): All business logic runs in Lambda functions (CRUD handlers). Use Spring Cloud Function or Function beans for easy adaptation.
- API Gateway: REST endpoints (e.g., /members, /activities) using AWS_PROXY integration to Lambda.
- Aurora Serverless v2 (MySQL): Relational storage accessed via RDS Data API from Lambda (no persistent DB connections).
- Amazon S3: Store attachments and static assets (React build if chosen).
- CloudFormation: Define stacks for Lambda, API Gateway, S3, IAM Roles, and optionally Aurora cluster skeleton.
- CloudWatch & Budgets: Logs, metrics, and budget alerts for cost control.
API & Endpoints
| HTTP | Path | Action |
| GET | /members | List members (pagination) |
| POST | /members | Create member |
| GET | /members/{id} | Get by ID |
| PUT | /members/{id} | Update member |
| DELETE | /members/{id} | Delete member |
| POST | /activities | Create activity |
| GET | /activities/{id} | Get activity details |
| POST | /activities/{id}/participants | Add participant |
| POST | /attachments | Upload file (S3) |
Implementation Details
1. Spring Boot Lambda (Java)
Use Spring Cloud Function to map functions to Lambda. For local testing you can keep a @RestController while providing Function beans for Lambda deployment.
Example Function bean
@Bean
public Function hello() {
return name -> "Hello, " + (name == null ? "World" : name) + "!";
}
2. RDS Data API (Aurora Serverless)
Create tables via the RDS Data API or migration scripts. Example SQL executed from Java:
ExecuteStatementRequest request = ExecuteStatementRequest.builder()
.resourceArn(System.getenv("DB_ARN"))
.secretArn(System.getenv("DB_SECRET"))
.database("ChurchDB")
.sql("CREATE TABLE IF NOT EXISTS Members (...)")
.build();
rdsClient.executeStatement(request);
3. File uploads to S3
S3Client s3 = S3Client.create();
s3.putObject(PutObjectRequest.builder()
.bucket(System.getenv("S3_BUCKET"))
.key("members/" + memberId + "/photo.jpg")
.build(), RequestBody.fromFile(Paths.get("photo.jpg")));
4. Sending notifications (SNS)
SnsClient sns = SnsClient.create();
sns.publish(PublishRequest.builder()
.topicArn("arn:aws:sns:...:NewMemberTopic")
.message("A new member was added")
.build());
CloudFormation Template Example (Skeleton)
AWSTemplateFormatVersion: '2010-09-09'
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties: ...
HelloLambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: HelloSpringLambda
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
Runtime: java17
Role: !GetAtt LambdaExecutionRole.Arn
Code:
S3Bucket: your-bucket-name
S3Key: your-springboot-lambda.jar
HelloApi:
Type: AWS::ApiGateway::RestApi
Properties: ...
LambdaPermissionForApi:
Type: AWS::Lambda::Permission
Properties: ...
Deploy Steps
- Package Spring Boot app as a fat JAR:
mvn clean package.
- Upload JAR to S3:
aws s3 cp target/app.jar s3://your-bucket/.
- Deploy CloudFormation stack:
aws cloudformation deploy --template-file template.yaml --stack-name ChurchStack --capabilities CAPABILITY_IAM.
- Find API Gateway URL and test with curl or Postman.
React Frontend: Hello World
Two options to serve React:
- S3 + CloudFront (recommended): Upload
build/ folder to S3 and use CloudFront for CDN and HTTPS.
- Lambda static server (demo): Package build files into a Node.js Lambda that serves
index.html.
React fetch example calling API
fetch('https://{api}.execute-api.us-east-1.amazonaws.com/dev/hello', {
method: 'POST',
body: JSON.stringify('Manuela')
}).then(r => r.text()).then(console.log);
Local Development Workflow
- Run Spring Boot locally with
mvn spring-boot:run and test @RestController endpoints.
- Run React locally with
npm start. Use a proxy to the local backend for easy testing.
- Use LocalStack for local testing of AWS services if needed.
- When ready, build frontend and backend and deploy via CloudFormation/SAM.
Cost Management & Estimates
This architecture is designed to be cost-efficient. For small demo usage expect monthly costs near $0 — typically under $5 if used lightly.
- Lambda: 1M free requests/month.
- API Gateway (HTTP API): ~$1 per million requests.
- Aurora Serverless v2: billed per ACU-hour; auto-pauses to reduce cost.
- S3: ~$0.023/GB-month for Standard storage.
AWS SDK Tasks You Can Implement
- S3 (Storage)
- Upload, download, list, delete files; generate presigned URLs for secure client uploads.
- Aurora / RDS Data API
- Execute SQL statements, create tables, run queries from Lambda using RdsDataClient.
- DynamoDB (optional)
- PutItem, GetItem, Query, Scan — useful as a low-cost alternative for simple schemas.
- SNS / SQS
- Publish notifications, decouple heavy tasks with queues, trigger asynchronous workers.
- SES
- Send transactional emails (welcome confirmations, alerts).
- Secrets Manager / KMS
- Store DB credentials; decrypt sensitive data; follow security best practices.
- CloudFormation
- Deploy stacks programmatically and manage updates.
- CloudWatch
- Push custom metrics, create alarms, and collect logs for observability.
Interview Tips & Demonstration Ideas
- Show a live demo: create a member via API Gateway and then view the record via DBeaver (if Aurora public) or a read API.
- Explain cost-control decisions: using Aurora Serverless, DynamoDB as alternative, and budgeting alerts.
- Show CloudFormation template and walk through resources it creates.
- Demonstrate local development flow and deployment steps.